2015-10-22 2 views
2

Мне любопытно узнать, что на самом деле происходит при поразрядном сравнении, используя бинарные литералы. Я просто наткнулся на следующую вещь:Поведение побитового xor с использованием бинарных литералов

byte b1 = (new Byte("1")).byteValue(); 

// check the bit representation 
System.out.println(String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0')); 
// output: 00000001 

System.out.println(b1^0b00000001); 
// output: 0 

Так что все ведет себя, как и ожидалось, xor сравнение равна 0. Однако при попытке же с отрицательным числом он не будет работать:

byte b2 = (new Byte("-1")).byteValue(); 

// check the bit representation 
System.out.println(String.format("%8s", Integer.toBinaryString(b2 & 0xFF)).replace(' ', '0')); 
// output: 11111111 

System.out.println(b2^0b11111111); 
// output: -256 

я ожидал бы, что последнее xor сравнение также равна 0. Однако это только в том случае, если я делать явное приведение из двоичного литерала byte:

byte b2 = (new Byte("-1")).byteValue(); 

// check the bit representation 
System.out.println(String.format("%8s", Integer.toBinaryString(b2 & 0xFF)).replace(' ', '0')); 
// output: 11111111 

System.out.println(b2^(byte)0b11111111); 
// output: 0 

Для меня это выглядит, что перед xor сравнения как b1 и 0b11111111 имеют одинаковое представление битов, так что даже если они литой до int (или что-то еще) xor должен по-прежнему равняться 0. Как вы попадаете в результат -256, который является 11111111 11111111 11111111 00000000 в двоичном представлении? Почему я должен сделать явный листинг до byte, чтобы получить 0?

+2

Те целые литералы, записанные в двоичной системе счисления. Более того, бинарные операторы продвигают свои операнды. –

+0

Хорошо! Поэтому я вижу, что происходит: '0b11111111' является двоичным представлением' 255' и на самом деле является целым числом. Таким образом, 'b2' получает значение в' int', которое (от построения) равно '-1'. Итак, что происходит, это побитовое 'xor'' -1' и '255' (в 32-битном представлении), которое дает' -256'. Если я сделаю cast '(byte) 0b11111111', то сравнение будет выполнено без приведения в' int', но только для 8 бит обоих выражений. Правильно? –

ответ

0

Двоичные литералы без определенного литья представляют собой 32-битные целочисленные значения, независимо от того, сколько их цифр. Например, 0b00000001 является сокращением для 0b00000000 00000000 00000000 00000001.

Поразрядные сравнения в Java используют двоичное числовое продвижение (см. Javadocs). В этом конкретном случае это означает, что оба операнда преобразуются в int перед выполнением сравнения.

0b11111111 уже что представляет собой int (без ведущих 0 сек) и просто представляет 0b00000000 00000000 00000000 11111111, в то время как b2 является байтами, представляющих значения -1. Во время преобразования в int значение сохраняется и, следовательно, b2 передается в 32-разрядное целое число, представляющее такое же число (-1): 0b11111111 11111111 11111111 11111111.

xor затем оценивает 0b11111111 11111111 11111111 00000000, который представляет собой 32-разрядное двоичное представление -256.

В случае xor сравнения выполняется с помощью (byte)0b11111111 двоичных буквальная также будут рассматриваться как один байты и, следовательно, что то же самое, приведенная к 32-разрядному целому числу, представляющему -1.

Важно отметить, что бинарные сравнения выполняются либо с double, float, long, либо с int (как указано в Javadocs). Если в сравнении участвуют только другие типы (например, byte), они будут преобразованы в int. Поэтому следующий фрагмент кода будет давать ошибку компиляции:

byte b1 = (byte)0b00000001; 
byte b2 = (byte)0b00000001; 
byte b3 = b1 & b2; 

>>> error: incompatible types: possible lossy conversion from int to byte 

... так как результат сравнения побитового два byte является int.

Дальнейшее чтение о почему можно сделать здесь:

0

При использовании b1^0b11111111 вы на самом деле xor между байтом к Int byte является 8 бит переменной, а int 32-разрядное число. Итак, что вы сделали это: b1^0b(00000000 00000000 00000000 11111111) поэтому при использовании xor между byte (с дополнительной 1s, прежде чем использовать его с INT 1s, потому что это negetive номер Если бы это было положительным, было бы 0s..) И int результат будет целым и в вашем случае -256.

При нажатии целого числа на byte вы используете xor между двумя байтами, и результат будет байтом.

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