c# - Strange behavior with << operator -
when dealing c# shift operators, encountered unexpected behavior of shift-left operator.
tried simple function:
for (int = 5; >= -10; i--) { int s = 0x10 << i; debug.writeline(i.tostring().padleft(3) + " " + s.tostring("x8")); } with result:
5 00000200 4 00000100 3 00000080 2 00000040 1 00000020 0 00000010 -1 00000000 -> 00000008 expected -2 00000000 -> 00000004 expected -3 00000000 -> 00000002 expected -4 00000000 -> 00000001 expected -5 80000000 -6 40000000 -7 20000000 -8 10000000 -9 08000000 -10 04000000 until today, expected << operator can deal negative values of second operand.
msdn tells nothing behavior when using negative values of second operand. msdn says lower 5 bits (0-31) used operator, should fit negative values.
i tried long values: long s = 0x10l << i;, same result.
so happens here?
edit
stated in answers, negative value representation not reason this.
got same wrong result cases:
0x10<<-3 = 0x00000000 (wrong!) 0x10<<(int)(0xfffffffd) = 0x00000000 (wrong!) 0x10<<(0x0000001d = 0x00000000 (wrong!) expected = 0x00000002 edit #2
1 of these 2 should true:
1) shift operator real shift-operator, results should be:
1a) 0x10 << -3 = 00000002
1b) 0x10 << -6 = 00000000
2) shift operator rotate-operator, results should be:
2a) 0x10 << -3 = 00000002 (same 1a)
2b) 0x10 << -6 = 40000000
but shown results not fit either 1) nor 2) !!!
negative numbers 2 complemented, -1 == 0xffffffff, , 0xffffffff & 31 == 31, -2 == 0xfffffffe, , 0xfffffffe & 31 == 30 , on.
-10 == 0xfffffff6, , 0xfffffff6 & 31 == 22, in fact: (0x10 << 22) == 04000000 some code show:
const int num = 0x10; int maxshift = 31; (int = 5; >= -10; i--) { int numshifted = num << i; uint ui = (uint)i; int uiwithmaxshift = (int)(ui & maxshift); int numshifted2 = num << uiwithmaxshift; console.writeline("{0,3}: {1,8:x} {2,2} {3,8:x} {4,8:x} {5}", i, ui, uiwithmaxshift, numshifted, numshifted2, numshifted == numshifted2); } with long it's same, instead of & 31 have & 63. -1 == 63, -2 == 62 , -10 == 54
some example code:
const long num = 0x10; int maxshift = 63; (int = 5; >= -10; i--) { long numshifted = num << i; uint ui = (uint)i; int uiwithmaxshift = (int)(ui & maxshift); long numshifted2 = num << uiwithmaxshift; console.writeline("{0,3}: {1,8:x} {2,2} {3,16:x} {4,16:x} {5}", i, ui, uiwithmaxshift, numshifted, numshifted2, numshifted == numshifted2); } just clear:
(int x) << y == (int x) << (int)(((uint)y) & 31) (long x) << y == (long x) << (int)(((uint)y) & 63) and not
(int x) << y == (int x) << (math.abs(y) & 63) (long x) << y == (long x) << (math.abs(y) & 63) and think "should be" "it beautiful if was" "has be" ecc irrelevant. while 1 , 0 "near" (their binary representation has "distance" of 1 in number of different bits), 0 , -1 "far" (their binary representation has "distance" of 32 or 64 in number of different bits)
you think should this:
-1 00000000 -> 00000008 expected -2 00000000 -> 00000004 expected -3 00000000 -> 00000002 expected -4 00000000 -> 00000001 expected but in truth don't see getting this:
-1 (00000008) 00000000 -2 (00000004) 00000000 -3 (00000002) 00000000 -4 (00000001) 00000000 -5 (00000000) 80000000 <-- show "symmetry" , "order" still exist -6 (00000000) 40000000 <-- show "symmetry" , "order" still exist where part in (...) part "left" of int , doesn't exist.
Comments
Post a Comment