在C#中使用无符号右移,使用Java语义处理负数。

6

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

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

这相当于Java中的:

long l = number >>> 2;

然而,对于您可能认为是Integer.MIN_VALUE-2147483648L的情况,由于将其转换为ulong会改变数字的语义,因此这将返回与Java中不同的数字,因此我得到了不同的结果。

在C#中,类似这样的事情如何实现?

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


5
你的括号放置可能有问题(从而导致不同/意外的运算顺序)吗?例如,将你的数字与 (long) ((ulong) number) >> 2 的示例代码进行移位会产生 -536870912 的结果,而将 ulong 转换(和移位)用括号包起来 (long) (((ulong) number) >> 2) 可以获得 4611686017890516992 的结果。编辑:我认为你的第一个示例在移位之前将 number 转换为 ulong,然后再转回 long,而我的表达式是先将其转换为 ulong,进行移位,然后再转回 long - Chris Sinclair
1
我感觉很愚蠢,为了这么琐碎的问题一直在寻找复杂的答案!你能把它发布为答案,这样我就可以接受它了吗?谢谢。 - Shai Almog
1个回答

5
我认为在考虑C#的顺序优先级时,您的表达式是不正确的。我相信您的代码是将long转换为ulong,然后再转换回long然后进行位移操作。我假设您的意图是对ulong执行位移操作。
根据C#规范§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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接