Right shift operator used for checking number negativity - c#

I am trying to check of a number is negative without using comparison operators. I am trying to examine the most significant bit. I am doing the following :
int x = -5;
Console.WriteLine(x >> 31);
I was expecting the output to be 1. But I get -1. What explains this behavior?

That's because operator >> on an int behaves as an arithmetic shift: the bits that are "pushed in" take the value of the sign bit (either 0 or 1, 1 in your case). So the resulting number you get is 0xFFFFFFFF, that is -1.
From MSDN:
If the first operand is an int or long, the right-shift is an
arithmetic shift (high-order empty bits are set to the sign bit). If
the first operand is of type uint or ulong, the right-shift is a
logical shift (high-order bits are zero-filled).
If you do:
Console.WriteLine((uint)x >> 31);
This is a logical shift, the higher bits are filled with 0, and the output is the one you expected: 1.

Related

integer promotion in c# (the range of an sbyte as an example)

so I am studying about Integer Promotion and I know that type promotions only apply to the values operated upon when an expression is evaluated.
I have this example where I take an sbyte that is equal to 127 and increment it by 1 and then I output it on the Console and I get a -128. Does this mean that the sbyte turns into an int during the process of incrementing and then it somehow transforms into a -128.
I would like to know how exactly this happens.
sbyte efhv = 127;
efhv++;
Console.WriteLine(efhv);
As #Sweeper pointed out in the comments, integer promotion does not apply to the ++ operator: ++ modifies the value in-place, which means that the modified value must be within the range of the
specified data type. Integer promotion would not make any sense here.
As #beautifulcoder explained in their answer, the effect you see is simply a two's complement number overflowing, since C# executes arithmetic operations in an unchecked context by default.
According to the C# language specification integer promotion does occur for the unary + and the binary + operators, as can be seen in the following code example:
sbyte efhv = 127;
sbyte one = 1;
Console.WriteLine((efhv).GetType().Name); // prints SByte
Console.WriteLine((efhv++).GetType().Name); // prints SByte
Console.WriteLine((+efhv).GetType().Name); // prints Int32
Console.WriteLine((efhv + one).GetType().Name); // prints Int32
(fiddle)
It is because this is a signed 8-bit integer. When the value exceeds the max it overflows into the negative numbers. It is not promotion but overflow behavior you are seeing.
To verify:
sbyte efhv = 127;
efhv++;
Console.WriteLine(efhv);
Console.WriteLine(sbyte.MaxValue);
Console.WriteLine(sbyte.MinValue);

Why is the following bitshift operation not discarding the bit shifted to the left?

Let's say I wrote the following :
Console.WriteLine("{0:X8}", (uint)1 << 31);
It returns 80000000 (as expected).
However, If I wrote :
Console.WriteLine("{0:X8}", (uint)1 << 32);
It returns 00000001.
I would expect the "1" bit to be discarded and the result to be 00000000.
Here is what documentation says :
The left-shift operation discards the high-order bits that are outside
the range of the result type and sets the low-order empty bit
positions to zero.
Indeed, if I wrote this :
Console.WriteLine("{0:X8}", (uint)0xFA << 28);
It returns A0000000 (F is discarded)
From that same documentation page:
For the x << count and x >> count expressions, the actual shift count depends on the type of x as follows:
If the type of x is int or uint, the shift count is defined by the low-order five bits of the right-hand operand. That is, the shift count is computed from count & 0x1F (or count & 0b_1_1111).
32 & 0x1F is 0.
This "gotcha" is bad enough that former C# design team member Eric Lippert named it the 8th worst C# feature.

c# uint right bit-shift unexpected result

I am confused why does this produce 0xffffffff in C#, I was expecting it to produce 0x0. The type of the expression is uint.
Console.WriteLine(0xffffffff >> 32);
As per the documentation:
If the first operand is an int or uint (32-bit quantity), the shift
count is given by the low-order five bits of the second operand
(second operand & 0x1f).
The second operand is 32. 32 & 0x1f is 0. Thus >> 32 is equivalent to 'shift this by 0 bits' therefore 'do nothing at all'.

operator >> in C# [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What does the “>>” operator in C# do?
Also related: Doubling a number - shift left vs. multiplication
This is code in C#.
I just need to know if I'm right.
I'm not sure with using operator >>.
this code:
winHalfWidth = this.ClientSize.Width >> 1; // both is int
make the same as:
winHalfWidth = this.ClientSize.Width / 2;
and if I'm right so, this code should do:
quaterWidht = this.ClientSize.Width >> 2;
should do same as:
quaterWidth = this.ClientSize.Width / 4;
So 2 questions:
Is it right?
Is any difference between using >> and /?
When we speak about int values?
When we speak abou float values? (I thing there could be.. but I'am not sure.)
Answers like yes/no would be nice :)
Thanks.
It does in fact do what you intend with int values, but you should be careful about edge cases such as negative numbers or very big numbers.
As for floating-point numbers, their memory representation is not that simple, so a simple shift-right won't do the trick of dividing by 2.
This is shift operator not divide , we know that shift left will multiply a number by 2 , For exmaple
2 in base 2 is : 0010 , if we shift it one times to left it will turn to 4 or 0100.
So as MSDN said :
If the first operand is an int or uint (32-bit quantity), the shift count is given by the low-order five bits of the second operand (second operand & 0x1f).
If the first operand is a long or ulong (64-bit quantity), the shift count is given by the low-order six bits of the second operand (second operand & 0x3f).
If the first operand is an int or long, the right-shift is an arithmetic shift (high-order empty bits are set to the sign bit). If the first operand is of type uint or ulong, the right-shift is a logical shift (high-order bits are zero-filled).

Why arithmetic shift halfs a number only in SOME incidents?

Hey, I'm self-learning about bitwise, and I saw somewhere in the internet that arithmetic shift (>>) by one halfs a number. I wanted to test it:
44 >> 1 returns 22, ok
22 >> 1 returns 11, ok
11 >> 1 returns 5, and not 5.5, why?
Another Example:
255 >> 1 returns 127
127 >> 1 returns 63 and not 63.5, why?
Thanks.
The bit shift operator doesn't actually divide by 2. Instead, it moves the bits of the number to the right by the number of positions given on the right hand side. For example:
00101100 = 44
00010110 = 44 >> 1 = 22
Notice how the bits in the second line are the same as the line above, merely
shifted one place to the right. Now look at the second example:
00001011 = 11
00000101 = 11 >> 1 = 5
This is exactly the same operation as before. However, the result of 5 is due to the fact that the last bit is shifted to the right and disappears, creating the result 5. Because of this behavior, the right-shift operator will generally be equivalent to dividing by two and then throwing away any remainder or decimal portion.
11 in binary is 1011
11 >> 1
means you shift your binary representation to the right by one step.
1011 >> 1 = 101
Then you have 101 in binary which is 1*1 + 0*2 + 1*4 = 5.
If you had done 11 >> 2 you would have as a result 10 in binary i.e. 2 (1*2 + 0*1).
Shifting by 1 to the right transforms sum(A_i*2^i) [i=0..n] in sum(A_(i+1)*2^i) [i=0..n-1]
that's why if your number is even (i.e. A_0 = 0) it is divided by two. (sorry for the customised LateX syntax... :))
Binary has no concept of decimal numbers. It's returning the truncated (int) value.
11 = 1011 in binary. Shift to the right and you have 101, which is 5 in decimal.
Bit shifting is the same as division or multiplication by 2^n. In integer arithmetics the result gets rounded towards zero to an integer. In floating-point arithmetics bit shifting is not permitted.
Internally bit shifting, well, shifts bits, and the rounding simply means bits that fall off an edge simply getting removed (not that it would actually calculate the precise value and then round it). The new bits that appear on the opposite edge are always zeroes for the right hand side and for positive values. For negative values, one bits are appended on the left hand side, so that the value stays negative (see how two's complement works) and the arithmetic definition that I used still holds true.
In most statically-typed languages, the return type of the operation is e.g. "int". This precludes a fractional result, much like integer division.
(There are better answers about what's 'under the hood', but you don't need to understand those to grok the basics of the type system.)

Categories