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

Popular posts from this blog

matlab - Deleting rows with specific rules -

php - MySQLi multi_query results for later use -