为什么F#Bitwise运算符用1表示签名类型?

时间:2010-09-29 21:44:25

标签: c# c++ f# history bit-shift

我在按位操作上查看F#doc:

  

按位右移运算符。该   result是第一个带位的操作数   向右移动了位数   第二个操作数。比特转移了   最不重要的位置不是   旋转到最重要的   位置。对于无符号类型,最多   有效位用填充   零。对于签名类型,最多   有效位用1填充。   第二个参数的类型是   INT32。

与C ++语言(也可能是C语言)相比,这种设计选择的动机是什么,其中MSB用零填充? E.g:

int mask = -2147483648 >> 1; // C++ code

其中-2147483648 =

10000000 00000000 00000000 00000000

和掩码等于1073741824

其中1073741824 =

01000000 00000000 00000000 00000000

现在,如果你在F#(或C#)中编写相同的代码,这确实会填充MSB,你将得到-1073741824。

其中-1073741824 =

11000000 00000000 00000000 00000000

2 个答案:

答案 0 :(得分:6)

有符号的移位有一个很好的属性,即右移n对应于floor(x / 2 n )。

在.NET上,两种类型的操作都有CIL操作码(shr执行签名移位,shr.un执行无符号移位操作。 F#和C#根据要移位的类型的符号选择要使用的操作码。这意味着如果你想要其他行为,你只需要在移位之前和之后执行数字转换(由于数据存储在CLR上的方式实际上没有运行时影响 - 堆栈上的int32与uint32无法区分) 。

答案 1 :(得分:5)

回答改革后的问题(在评论中):

C和C ++标准没有定义右移一个负值的结果(它是实现定义的,还是未定义的,我不记得哪个)。

这是因为标准被定义为反映基础指令集的最低公分母。例如,如果指令集不包含asr原语,则执行真正的算术移位需要几条指令。由于标准要求 二的补码表示,这使事情变得更加复杂。