Для записи сложных сравнений следует привлекать логические операции. Например, в вычислениях часто приходится делать проверки вида a < x < b. Подобная запись на языке Java приведет к сообщению об ошибке, поскольку первое сравнение, a < x, даст true или false, а Java не знает, больше это, чем ь, или меньше. В данном случае следует написать выражение (a < x) && (x < b), причем здесь скобки можно опустить, написать просто a < x && x < b, но об этом немного позднее.
Побитовые операции
Иногда приходится изменять значения отдельных битов в целых данных. Это выполняется с помощью побитовых (bitwise) операций, как говорят, "наложением маски".
В языке Java четыре побитовые операции:
□ дополнение (complement)--(тильда);
□ побитовая конъюнкция (bitwise AND) — &;
□ побитовая дизъюнкция (bitwise OR) — |;
□ побитовое исключающее ИЛИ (bitwise XOR) — л.
Они выполняются поразрядно, после того как оба операнда будут приведены к одному типу int или long, так же как и для арифметических операций, а значит, и к одной разрядности. Операции над каждой парой битов выполняются согласно табл. 1.3.
n1 | n2 | ~n1 | n1 & n2 | n1 | n2 | n1 л n2 |
1 | 1 | 0 | 1 | 1 | 0 |
1 | 0 | 0 | 0 | 1 | 1 |
0 | 1 | 1 | 0 | 1 | 1 |
0 | 0 | 1 | 0 | 0 | 0 |
В нашем примере число bi == 50, его двоичное представление 00110010, число b2 == -99, а его двоичное представление равно 10011101. Перед операцией происходит повышение типа byte до типа int. Получаем представления из 32-х разрядов для b1 — 0...00110010, а для b2 — 1...10011101. В результате побитовых операций получаем:
□ ~b2 == 98, двоичное представление — 0...01100010;
□ b1 & b2 == 16, двоичное представление — 0...00010000;
□ b1 | b2 == -65, двоичное представление — 1...10111111;
□ b1 Л b2 == -81, двоичное представление — 1...10101111.
Двоичное представление каждого результата занимает 32 бита.
Заметьте, что дополнение ~x всегда эквивалентно разности (-x) -1.
Сдвиги
В языке Java есть три операции сдвига двоичных разрядов:
□ сдвиг влево — <<;
□ сдвиг вправо — >>;
□ беззнаковый сдвиг вправо — >>>.
Эти операции своеобразны тем, что левый и правый операнды в них имеют разный смысл. Слева стоит значение целого типа, а правая часть показывает, на сколько двоичных разрядов сдвигается значение, стоящее в левой части.
Например, операция b1 << 2 сдвинет влево на 2 разряда предварительно повышенное значение 0...00110010 переменной b1, что даст в результате 0...011001000, десятичное число — 200. Освободившиеся справа разряды заполняются нулями; левые разряды, находящиеся за 32-м битом, теряются.
Операция b2 << 2 сдвинет повышенное значение 1...10011101 на два разряда влево. В результате получим 1...1001110100, десятичное значение--396.
Заметьте, что сдвиг влево на n разрядов эквивалентен умножению числа на 2 в степени n.
Операция b1 >> 2 даст в результате 0...00001100, десятичное — 12, а b2 >> 2 — результат
1...11100111, десятичное--25, т. е. слева распространяется старший бит, правые биты
теряются. Это так называемый
Операция беззнакового сдвига во всех случаях ставит слева на освободившиеся места нули, осуществляя
Если же мы хотим получить логический сдвиг исходного значения 10011101 переменной b2, т. е. 0...00100111, надо предварительно наложить на b2
(b2 & 0xFF) >>> 2.
Будьте осторожны при использовании сдвигов вправо.
3. Каково значение выражения ' D' + 5?
При определениях, сделанных ранее, вычислите выражения:
4. (b1 + с1) % (++b2 / b1++).
5. (b1 < с1) && (b2 == -99) || (ind >= 0).
6. (b1 | с1) & (big Л b1).
7. (b1<<3 + с1<<2) % (b2>>5 / b1>>>2).
Вещественных типов в Java два: float и double. Они характеризуются разрядностью, диапазоном значений и точностью представления, отвечающим стандарту IEEE 7541985 с некоторыми изменениями. К обычным вещественным числам добавляются еще три значения:
□ положительная бесконечность, выражаемая константой positive_infinity и возникающая при переполнении положительного значения, например в результате операции умножения 3.0*6e307 или при делении на нуль;
□ отрицательная бесконечность negative_infinity, возникающая при переполнении отрицательного значения, например в результате операции умножения -3.0*6e307 или при делении на нуль отрицательного числа;
□ "не число", записываемое константой NaN (Not a Number) и возникающее, например, при умножении нуля на бесконечность.
В
Кроме того, стандарт различает положительный и отрицательный нуль, возникающий при делении на бесконечность соответствующего знака, хотя сравнение 0.0 == -0.0 дает в результате истину, true.