C#中的无符号移位使用Java语义来表示负数

Sha*_*mog 6 c# java bit-manipulation

我正在尝试将Java代码移植到C#,我遇到了与无符号右移操作符相关的奇怪错误>>>通常代码:

long l = (long) ((ulong) number) >> 2;
Run Code Online (Sandbox Code Playgroud)

将相当于Java:

long l = number >>> 2;
Run Code Online (Sandbox Code Playgroud)

但是对于-2147483648L你可能认识到的情况,这会Integer.MIN_VALUE返回一个不同于Java的数字,因为强制转换会ulong改变数字的语义,因此我得到了不同的结果.

在C#中,这样的事情怎么可能?

我想尽可能保留代码语义,因为它是一个非常复杂的代码体.

Chr*_*air 5

在考虑C#的顺序优先级时,我认为你的表达式是不正确的.你的代码,我认为这是你转换longulong,然后回long,然后转移.我假设你的意图是执行转变ulong.

根据C#规范§7.2.1,一元(或在您的情况下,铸造操作)优先于移位.因此你的代码:

long l = (long) ((ulong) number) >> 2;
Run Code Online (Sandbox Code Playgroud)

将被解释为:

ulong ulongNumber = (ulong)number;
long longNumber = (long)ulongNumber;
long shiftedlongNumber = longNumber >> 2;
Run Code Online (Sandbox Code Playgroud)

鉴于number作为-2147483648L,这会产生536870912.

通过包装转换并在括号中移位:

long l = (long) (((ulong) number) >> 2);
Run Code Online (Sandbox Code Playgroud)

产生可以重写为的逻辑:

ulong ulongNumber = (ulong)number;
ulong shiftedulongNumber = ulongNumber >> 2;
long longShiftedNumber = (long)shiftedulongNumber;
Run Code Online (Sandbox Code Playgroud)

这给出number-2147483648L,这产生了4611686017890516992.


编辑:请注意,鉴于这些排序规则,我的答案中有一组额外的括号,这是不必要的.正确的表达式可以写成:

long l = (long) ((ulong) number >> 2);
Run Code Online (Sandbox Code Playgroud)