Dlaczego 11010100 << 1 oznacza 110101000, a nie 10101000?

40

Dlaczego, kiedy próbuję przesunąć bity dla 11010100 2 , wynik to 110101000 2 , a nie 10101000 2 .

int a = Integer.parseInt("11010100", 2) << 1;

Próbuję to zrobić:

int a = (byte)(Integer.parseInt("11010100", 2) << 1);

Ale jeśli wartość wyjściowa jest większa niż 128, wszystko idzie w minus, co jest logiczne. Jak mogę sprawić, że ta liczba bitów się nie zmienia?

Jaroszenko Jarosław
źródło
4
Arytmetyka liczb całkowitych jest zawsze wykonywana na ints lub longs.
Tom Hawtin - tackline
34
Używasz liczb całkowitych o długości 32 bitów. Dlaczego miałbyś oczekiwać, że wynik zostanie skrócony do 8 bitów?
jhamon
1
bajt a = ... to naprawi.
Perdi Estaquel

Odpowiedzi:

61

Zróbmy to krok po kroku.

  1. Integer.parseInt("11010100", 2)- to jest wartość int 212. Nawiasem mówiąc, jest to niepotrzebne; można po prostu napisać: 0b11010100.

  2. 0b11010100 << 1jest taki sam jak 0b110101000i wynosi 424.

  3. Następnie wrzucił je do bajta: (byte)(0b11010100 << 1). Wszystkie bity poza pierwszymi 8 są usuwane, co pozostawia 0b10101000, czyli -88. Minus, tak, ponieważ w java bajty są podpisane.

  4. Następnie po cichu rzutujesz to -88 z powrotem na int, przypisując go do wartości int. Pozostaje -88, co oznacza, że ​​wszystkie górne bity to wszystkie 1.

Dlatego ostateczna wartość to -88.

Jeśli chcesz zobaczyć 168zamiast tego (dokładnie te same bity, ale pokazane bez znaku zamiast z podpisem), zwykle używa się sztuczki & 0xFF, która ustawia wszystkie bity z wyjątkiem pierwszych 8 na 0, gwarantując w ten sposób liczbę dodatnią:

byte b = (byte) (0b11010100 << 1);
System.out.println(b); // -88. It is not possible to print 168 when printing a byte.
int asUnsigned = b & 0xFF;
System.out.println(asUnsigned); // 168.

// or in one go:

System.out.println(((byte) (0b11010100 << 1)) & 0xFF); // 168
rzwitserloot
źródło
19
Przechowuje wartość w int a, więc jeśli masz & 0xFF, to nie musisz w ogóle rzucać. int a = (0b11010100<< 1) & 0xFF;
Kaczka Mooing
9

Jeśli chcesz ustawić 0 na wszystkie bity wyższe niż dolne 8 bitów, możesz użyć bitów ORAZ:

int a = (Integer.parseInt("11010100", 2) << 1) & 0xff;
System.out.println (Integer.toString(a,2));

Wynik:

10101000
Eran
źródło
6

Wypróbuj coś takiego:

int anInt = Integer.parseInt("11010100", 2) << 1;
int asUnsignedInt= Byte.toUnsignedInt((byte) anInt);

toUnsignedInt został wprowadzony w Javie SE 8.

Kolor brązowofioletowy
źródło