I'm trying to port Java code to C# and I'm running into odd bugs related to the unsigned shift right operator >>> normally the code:
long l = (long) ((ulong) number) >> 2;
Would be the equivalent of Java's:
long l = number >>> 2;
However for the case of -2147483648L
which you might recognized as Integer.MIN_VALUE
this returns a different number than it would in Java since the cast to ulong
changes the semantics of the number hence I get a different result.
How would something like this be possible in C#?
I'd like to preserve the code semantics as much as possible since its a pretty complex body of code.
The unsigned right shift operator ( >>> ) (zero-fill right shift) evaluates the left-hand operand as an unsigned number, and shifts the binary representation of that number by the number of bits, modulo 32, specified by the right-hand operand.
It is a bitwise operator that we use in the C language for operating on bits. The right shift operator is binary- which means that the working of this operator would require two of the operands. We represent the right shift operator using the >> sign.
When shifting an unsigned value, the >> operator in C is a logical shift. When shifting a signed value, the >> operator is an arithmetic shift.
The bitwise shift operators move the bit values of a binary object. The left operand specifies the value to be shifted. The right operand specifies the number of positions that the bits in the value are to be shifted.
I believe your expression is incorrect when considering C#'s order precedence. Your code I believe is converting your long
to ulong
, then back to long
, then shifting. I'm assuming your intent was to perform the shift on the ulong
.
From the C# Specification §7.2.1, Unary (or in your case, the casting operation) takes precedence over the shifting. Thus your code:
long l = (long) ((ulong) number) >> 2;
would be interpreted as:
ulong ulongNumber = (ulong)number;
long longNumber = (long)ulongNumber;
long shiftedlongNumber = longNumber >> 2;
Given number
as -2147483648L
, this yields 536870912
.
By wrapping the conversion and shifting in parenthesis:
long l = (long) (((ulong) number) >> 2);
Produces logic that could be rewritten as:
ulong ulongNumber = (ulong)number;
ulong shiftedulongNumber = ulongNumber >> 2;
long longShiftedNumber = (long)shiftedulongNumber;
Which given number
as -2147483648L
, this yields 4611686017890516992
.
EDIT: Note that given those ordering rules, there's an extra set of parenthesis in my answer that aren't necessary. The correct expression could be written as:
long l = (long) ((ulong) number >> 2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With