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

时间:2014-01-17 14:26:09

标签: c# java bit-manipulation

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

long l = (long) ((ulong) number) >> 2;

相当于Java:

long l = number >>> 2;

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

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

我想尽可能保留代码语义,因为它是一个相当复杂的代码体。

1 个答案:

答案 0 :(得分:5)

我认为在考虑C#的顺序优先时你的表达式是不正确的。我相信您的代码会将long转换为ulong,然后转回long然后转换。我假设你的意图是在ulong上进行转变。

C# Specification §7.2.1,一元(或者在你的情况下,铸造操作)优先于移位。因此你的代码:

long l = (long) ((ulong) number) >> 2;

将被解释为:

ulong ulongNumber = (ulong)number;
long longNumber = (long)ulongNumber;
long shiftedlongNumber = longNumber >> 2;

number视为-2147483648L,这会产生536870912

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

long l = (long) (((ulong) number) >> 2);

生成可以重写为的逻辑:

ulong ulongNumber = (ulong)number;
ulong shiftedulongNumber = ulongNumber >> 2;
long longShiftedNumber = (long)shiftedulongNumber;

其中number-2147483648L,这会产生4611686017890516992


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

long l = (long) ((ulong) number >> 2);