This question already has answers here:
What does the operator "<<" mean in C#?
(9 answers)
Closed 7 years ago.
i couldn't understand this code in c#
int i=4
int[] s =new int [1<<i];
Console.WriteLine(s.length);
the ouput is 16
i don't know why the output like that?
bit shift operator
From documentation
If first operand is an int or uint
(32-bit quantity), the shift count is
given by the low-order five bits of
second operand.
If first operand is a long or ulong
(64-bit quantity), the shift count is
given by the low-order six bits of
second operand.
Note that i<<1 and i<<33 give the same
result, because 1 and 33 have the same
low-order five bits.
This will be the same as 2^( the actual value of the lower 5 bits ).
So in your case it would be 2^4=16.
I'm assuming you mean i in place of r...
<<n means "shift left by n* bits". Since you start with 1=binary 00...00001, if you shift left 4 times you get binary 00...10000 = 16 (it helps if you are familiar with binary arithmetic - otherwise "calc.exe" has a binary converter).
Each bit moves left n places, filling (on the right) with 0s. *=note that n is actually "mod 32" for int, so (as a corner case) 1 << 33 = 2, not 0 which you might expect.
There is also >> (right shift), which moves for the right, filling with 0 for uints and +ve ints, and 1 for -ve ints.
<< is the left shift operator
x << y
means shift x to the left by y bits.
3 is 0011, 3<<1 is 0110 which 6.
It's usually used to multiply by 2 (shifting to the left is multiplying by 2)
As already mentioned, << is the left shift operator. In your particular example, the array size is being defined as a power of 2. The value 1 shifted left by some number is going to be 1, 2, 4, 8, 16, ...
Related
I have the below code and I can't understand why the last line doesn't return 77594624. Can anyone help me write the inverse bitwise operation to go from 77594624 to 4 and back to 77594624?
Console.WriteLine(77594624);
Console.WriteLine((77594624 >> 24) & 0x1F);
Console.WriteLine((4 & 0x1F) << 24);
When you bit shift a value you might "lose" bits during that operation. If you right shift the value 16, which is 0b10000 in binary, by 4, you will get 1.
0b10000 = 16
0b00001 = 1
But this is also the case for other numbers like 28, which is 0b11100.
0b11100 = 28 = 16 + 8 + 4
0b00001 = 1
So with the start point 1 you cannot go "back" to the original number by left shifting again, as there is not enough information/bits available, you don't know if you want to go back to 16 or 28.
77594624 looks like this in binary, and the x's mark the part that is extracted by the right shift and bitwise AND:
000001000101000000000000000000000
xxxxx
Clearly some information is lost.
If the other parts of the number were available as well, then they could be reassembled.
Note I think some commenters misunderstand my question that I don't understand integer division and floating point division - More clarification: I expected -1/2 == -1 >> 1 == 0, but in fact -1 >> 1 = -1.
I'm learning two's complement. I understand a special thing about bit shifting in two's complement's context is that right shifting needs to maintain the sign of the bit, such that right shifting a negative number should fill in 1 instead of 0. And left shifting should always fill 0. This is explained in the Wikipedia's article.
According to the article, the motivation behind this is to maintain the equivalency of bit shifting operation and the corresponding multiplication or division by 2. However, a special case I immediately noticed is -1. Under the above mentioned rule, -1>>1 does not equal to -1/2.
My question is how should I understand this? And what precautions should I take when applying bit shifts in optimization of multiplication and division?
Here's a C# (should be equivalent in other languages) code illustrating what I meant:
class Program
{
static void Main(string[] args)
{
foreach (int x in new[] { 0, 1, 2, 3, -1, -2, -3 })
{
int a = x >> 1;
int b = x / 2;
Console.WriteLine($"Number:{x}, x>>1: {a}, x/2: {b}");
}
}
}
This produces the output of:
Number:0, x>>1: 0, x/2: 0
Number:1, x>>1: 0, x/2: 0
Number:2, x>>1: 1, x/2: 1
Number:3, x>>1: 1, x/2: 1
Number:-1, x>>1: -1, x/2: 0
Number:-2, x>>1: -1, x/2: -1
Number:-3, x>>1: -2, x/2: -1
You should not use shift operatings in your code, if you are trying to do division. The optimizer is able to figure this out better than you can. Of course, if you really know what you are doing and you are using unsigned integers entirely and you are writing in assembly, go ahead. Until then, just use the normal math operators for doing normal math operations.
If you are asking why -1 >> 1 == -1, well that's easy. The value negative one looks like all ones in binary, or 0xFFFFFFFF in hex. Shift the bits to the right and shift-in in a new 1 to the empty hole on the left, and you are left with what you started !
The results are still consistent. The effect that a right shift by 1 has is division by 2 rounded down.
In the case of an odd positive value, the "extra" 0.5 gets dropped. In the case of an odd negative value, it goes the other way.
In the examples you give above, half of -1 is -0.5, rounded down to -1. Similarly, half of -3 is -1.5, rounded down to -2.
Why does -1 >> 1 == -1?
Whenever you shift, the machine must fill in a missing value. We'll use four bits just to keep things simple. When you shift left, the bit that must be replaced is the trailing bit:
0101 << 1 // equivalent of 5 * 2
101_ // This is filled in with a zero
1010 // 5 * 2 == 10
When you shift right, the leading bit must be replaced. But since the leading bit determines sign in signed 2s complement, we don't want to lose that sign (shifting left, or int dividing by some power of 2, should never cause a negative number to become positive or vice versa). So the replacement value is whatever the leading (sign) bit already was:
0111 >> 1 // equivalent of 7 intdiv 2
_011 // Signed, so this is filled in with a zero
0011 // 7 intdiv 2 == 3
1111 >> 1 // equivalent of -1 intdiv 2, kinda
_111 // Signed, so this is filled in with a 1
1111 // -1 intdiv 2 == -1
However, if this was unsigned representation, the leading bit would simply be filled in with a zero:
1111 >> 1 // equivalent of 15 intdiv 2
_111 // Unsigned, so this is filled in with a 0
0111 // 15 intdiv 2 == 7
Further reading: https://msdn.microsoft.com/en-us/library/336xbhcz.aspx
The Wiki article is wrong for c. This statement: These rules preserve the common semantics that left shifts multiply the number by two and right shifts divide the number by two. is not correct for c when looking at odd negative integers.
For integer division c uses round towards zero (or truncation toward zero as it is stated in the standard), i.e. if the real result is 1.5 the integer result will be 1. If the real result is -1.5 the integer result will be -1.
For c the standard doesn't specify what should happen to negative integers when doing a right shift - it is implementation-defined.
If your system uses two's complement right shift doesn't work the same way as division. In general shifting has nothing to do with rounding. However, if you want to look at a two's complement right shift as a division, you got to notice that it rounds towards minus infinity. That is: if the real result is 1.5 the integer result will be 1. If the real result is -1.5 the integer result will be -2.
Conclusion: Rigth shift is not the same as division by 2 for odd negative integers.
Your direct question:
-1 >> 1 is ??
If you consider right shift as a division by 2, the real result would be -0.5 but since it works like round towards minus infinity, the result will be rounded to -1
But as stated - right shift is not a division by 2. You have to look at the bit level.
At bit level it is simply because the bit pattern for -1doesn't change.
In two's complement -1 is an all-ones bit pattern, e.g.
int a = -1; // Pattern 11111111.11111111.11111111.11111111
when you right shift a two complements integer being -1 you simply get the same bit pattern and therefore the same value. You shift out a 1at LSB and shift in a 1 at MSB. So the binary pattern stays the same.
So what happens to -3:
int a = -3; // Pattern 11111111.11111111.11111111.11111101
a = a >> 1; // Pattern 11111111.11111111.11111111.11111110 = -2
Consider this case:
-1 = 0b11
-1 >> 1 => 0b11 >> 1 => 0b11 (Many 1s on the left) (= -1)
If you look back -3 >> 1 case (prepare your computer's calc in programmer's mode)
you should see 0b111101 >> 1 becomes 0b111110 (-2)
This question already has answers here:
What are bitwise shift (bit-shift) operators and how do they work?
(10 answers)
Closed 8 years ago.
var x = 2;
var y=x+2<<2;
Console.WriteLine(y);
output = 16
my doubt is that how 16 is come.i know about bitwise shift left operator.what kind of operation is done.
Pay attention to operator precedence. 2 + 2 << 2 is not 2 + (2 << 2).
its same as below :-
x + 2 = 4;
4 << 2 ////it means 16 if you perform bitwise on this.
Desciption to understand Let shift operation :-
Shifts bits to the left. The number to the left of the operator is
shifted the number of places specified by the number to the right.
Each shift to the left doubles the number, therefore each left shift
multiplies the original number by 2. Use the left shift for fast
multiplication or to pack a group of numbers together into one larger
number. Left shifting only works with integers or numbers which
automatically convert to an integer such at byte and char.
so in your case lets say presentation for 4 is 100 and it would be shifted by 2 so it becomes 10000 which is presentation of 16 :-
for 4 :- 100
left shift by 2 so,
10000 ////Which is 16
(uint)Convert.ToInt32(elements[0]) << 24;
The << is the left shift operator.
Given that the number is a binary number, it will shift all the bits the specified amount to the left.
If we have
2 << 1
This will take the number 2 in binary (00000010) and shift it to the left one bit. This gives you 4 (000000100).
Overflows
Note that once you get to the very left, the bits are discarded. So assuming you are working with an 8 bit sized integer (I know c# uint like you have in your example is 32 bits - I dont want to have to type out a 32 bit digit, so just assume we are on 8 bits)
255 << 1
will return 254 (11111110).
Use
Being very careful of the overflows mentioned before, bit shifting is a very fast way to multiply or divide by 2. In a highly optimised environment (such as games) this is a very useful way to perform arithmetic very fast.
However, in your example, it is taking only the right most 8 bits of the number making them the left most 8 bits (multiplying it by 16,777,216) . Why you would want do this, I could only guess.
I guess you are referring to Shift operators.
As Mongus Pong said, shifts are usually used to multiply and divide very fast. (And can cause weird problems due to overflow).
I'm going to go out on a limb and trying to guess what your code is doing.
If elements[0] is a byte element(that is to say, it contains only 8 bits), then this code will result in straight-forward multiplication by 2^24. Otherwise, it will drop the 24 high-order bits and multiply by 2^24.
I am working on a little Hardware interface project based on the Velleman k8055 board.
The example code comes in VB.Net and I'm rewriting this into C#, mostly to have a chance to step through the code and make sense of it all.
One thing has me baffled though:
At one stage they read all digital inputs and then set a checkbox based on the answer to the read digital inputs (which come back in an Integer) and then they AND this with a number:
i = ReadAllDigital
cbi(1).Checked = (i And 1)
cbi(2).Checked = (i And 2) \ 2
cbi(3).Checked = (i And 4) \ 4
cbi(4).Checked = (i And 8) \ 8
cbi(5).Checked = (i And 16) \ 16
I have not done Digital systems in a while and I understand what they are trying to do but what effect would it have to AND two numbers? Doesn't everything above 0 equate to true?
How would you translate this to C#?
This is doing a bitwise AND, not a logical AND.
Each of those basically determines whether a single bit in i is set, for instance:
5 AND 4 = 4
5 AND 2 = 0
5 AND 1 = 1
(Because 5 = binary 101, and 4, 2 and 1 are the decimal values of binary 100, 010 and 001 respectively.)
I think you 'll have to translate it to this:
i & 1 == 1
i & 2 == 2
i & 4 == 4
etc...
This is using the bitwise AND operator.
When you use the bitwise AND operator, this operator will compare the binary representation of the two given values, and return a binary value where only those bits are set, that are also set in the two operands.
For instance, when you do this:
2 & 2
It will do this:
0010 & 0010
And this will result in:
0010
0010
&----
0010
Then if you compare this result with 2 (0010), it will ofcourse return true.
Just to add:
It's called bitmasking
http://en.wikipedia.org/wiki/Mask_(computing)
A boolean only require 1 bit. In the implementation most programming language, a boolean takes more than a single bit. In PC this won't be a big waste, but embedded system usually have very limited memory space, so the waste is really significant. To save space, the booleans are packed together, this way a boolean variable only takes up 1 bit.
You can think of it as doing something like an array indexing operation, with a byte (= 8 bits) becoming like an array of 8 boolean variables, so maybe that's your answer: use an array of booleans.
Think of this in binary e.g.
10101010
AND
00000010
yields 00000010
i.e. not zero. Now if the first value was
10101000
you'd get
00000000
i.e. zero.
Note the further division to reduce everything to 1 or 0.
(i and 16) / 16 extracts the value (1 or 0) of the 5th bit.
1xxxx and 16 = 16 / 16 = 1
0xxxx and 16 = 0 / 16 = 0
And operator performs "...bitwise conjunction on two numeric expressions", which maps to '|' in C#. The '` is an integer division, and equivalent in C# is /, provided that both operands are integer types.
The constant numbers are masks (think of them in binary). So what the code does is apply the bitwise AND operator on the byte and the mask and divide by the number, in order to get the bit.
For example:
xxxxxxxx & 00000100 = 00000x000
if x == 1
00000x00 / 00000100 = 000000001
else if x == 0
00000x00 / 00000100 = 000000000
In C# use the BitArray class to directly index individual bits.
To set an individual bit i is straightforward:
b |= 1 << i;
To reset an individual bit i is a little more awkward:
b &= ~(1 << i);
Be aware that both the bitwise operators and the shift operators tend to promote everything to int which may unexpectedly require casting.
As said this is a bitwise AND, not a logical AND. I do see that this has been said quite a few times before me, but IMO the explanations are not so easy to understand.
I like to think of it like this:
Write up the binary numbers under each other (here I'm doing 5 and 1):
101
001
Now we need to turn this into a binary number, where all the 1's from the 1st number, that is also in the second one gets transfered, that is - in this case:
001
In this case we see it gives the same number as the 2nd number, in which this operation (in VB) returns true. Let's look at the other examples (using 5 as i):
(5 and 2)
101
010
----
000
(false)
(5 and 4)
101
100
---
100
(true)
(5 and 8)
0101
1000
----
0000
(false)
(5 and 16)
00101
10000
-----
00000
(false)
EDIT: and obviously I miss the entire point of the question - here's the translation to C#:
cbi[1].Checked = i & 1 == 1;
cbi[2].Checked = i & 2 == 2;
cbi[3].Checked = i & 4 == 4;
cbi[4].Checked = i & 8 == 8;
cbi[5].Checked = i & 16 == 16;
I prefer to use hexadecimal notation when bit twiddling (e.g. 0x10 instead of 16). It makes more sense as you increase your bit depths as 0x20000 is better than 131072.