2013-04-17 6 views
0
public class Shift { 

    public static void main(String[] args) { 
     for(int i = 0; i < 32; ++i){ 
      System.out.println(-0x55555555 << i); 
     } 
    } 

} 

Запуск выше код дает следующий результатПодпись сдвиг влево поведение

-1431655765 
1431655766 
-1431655764 
1431655768 
-1431655760 
1431655776 
-1431655744 
1431655808 
-1431655680 
1431655936 
-1431655424 
1431656448 
-1431654400 
1431658496 
-1431650304 
1431666688 
-1431633920 
1431699456 
-1431568384 
1431830528 
-1431306240 
1432354816 
-1430257664 
1434451968 
-1426063360 
1442840576 
-1409286144 
1476395008 
-1342177280 
1610612736 
-1073741824 
-2147483648 

При тестировании с другим значением (64) дает более ожидаемого результата

public class Shift { 

    public static void main(String[] args) { 
     for(int i = 0; i < 32; ++i){ 
      System.out.println(-0x40 << i); 
     } 
    } 

} 

Выход

-64 
-128 
-256 
-512 
-1024 
-2048 
-4096 
-8192 
-16384 
-32768 
-65536 
-131072 
-262144 
-524288 
-1048576 
-2097152 
-4194304 
-8388608 
-16777216 
-33554432 
-67108864 
-134217728 
-268435456 
-536870912 
-1073741824 
-2147483648 
0 
0 
0 
0 
0 
0 

В the specs (§15.19) он сказал, что:

The value of n << s is n left-shifted s bit positions; this is equivalent (even if overflow occurs) to multiplication by two to the power s.

Может кто-то объяснить почему о первом выходе?

ответ

2

Значение n < < s - n позиций влево-сдвинутых положениях; это эквивалентно (даже если происходит переполнение) для умножения на два на степень s.

И это правда: это именно результат вы получите, если умножить на два -0x55555555 к власти s, из-за переполнения. В частности, 0x55555555 чередует 0s и 1s, поэтому вы перемещаете чередующиеся 0 и 1 в знаковый бит, поэтому знак перебрасывается каждый раз.

+0

Так почему же он сохраняет знак во втором примере? Что именно считается переполнением? –

+0

Он сохраняет знак во втором примере, потому что '-0x40' не имеет чередующихся 0 и 1 в его двоичном представлении; его двоичное представление равно '0xFFFFFFC0', поэтому он все равно имеет 1 для своего знакового бита, когда вы сдвигаете его влево (пока вы не сдвинете его достаточно далеко, чтобы это было 0). –

+0

Переполнение будет любым результатом, который «обычно» находится вне диапазона -2^31 <= x <2^31. –

Смежные вопросы