我在看F# doc的位操作:
按位右移运算符。结果是将第一个操作数的位右移第二个操作数中的位数。移出最低有效位置的位不会循环到最高有效位置。对于无符号类型,最高有效位用零填充。对于有符号类型,最高有效位用1填充。第二个参数的类型为int 32。
与 C++ (可能也是C语言)中MSB用零填充相比,这种设计选择背后的动机是什么?例如:
int mask = -2147483648 >> 1; // C++ code
其中-2147483648 =
10000000 00000000 00000000 00000000
掩码等于1073741824
其中1073741824 =
01000000 00000000 00000000 00000000
现在,如果你用F#(或C#)编写相同的代码,这确实会用1填充MSB,你会得到-1073741824。
其中-1073741824 =
11000000 00000000 00000000 00000000
2条答案
按热度按时间nbnkbykc1#
带符号移位有一个很好的性质,将x右移n对应于floor(x/2n)。
在.NET上,这两种类型的操作都有CIL操作码(
shr
执行有符号移位,shr.un
执行无符号移位)。F#和C#根据要移位的类型的有符号性来选择要使用的操作码。这意味着如果您想要其他行为,你只需要在移位前后执行一次数值转换(由于数字在CLR上的存储方式-堆栈上的int 32与uint 32无法区分,因此实际上对运行时没有影响)。ni65a41a2#
要回答改革后的问题(在评论中):
C和C++标准没有定义将负值右移的结果(要么是实现定义的,要么是未定义的,我记不清是哪一个了)。
这是因为该标准被定义为反映底层指令集的最小公分母。例如,如果指令集不包含
asr
原语,则强制执行真正的算术移位需要几条指令。由于该标准要求 * 要么 * 一的 * 要么 * 二的补码表示法,这使得情况更加复杂。