我在按位操作上查看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
答案 0 :(得分:6)
有符号的移位有一个很好的属性,即右移n对应于floor(x / 2 n )。
在.NET上,两种类型的操作都有CIL操作码(shr
执行签名移位,shr.un
执行无符号移位操作。 F#和C#根据要移位的类型的符号选择要使用的操作码。这意味着如果你想要其他行为,你只需要在移位之前和之后执行数字转换(由于数据存储在CLR上的方式实际上没有运行时影响 - 堆栈上的int32与uint32无法区分) 。
答案 1 :(得分:5)
回答改革后的问题(在评论中):
C和C ++标准没有定义右移一个负值的结果(它是实现定义的,还是未定义的,我不记得哪个)。
这是因为标准被定义为反映基础指令集的最低公分母。例如,如果指令集不包含asr
原语,则执行真正的算术移位需要几条指令。由于标准要求 或二的补码表示,这使事情变得更加复杂。