12

12


printC'c: " + Integer.toBinaryString(c));



byte b = 0x7f. // макс шестнадцатеричное знач. byte



printC'b " + Integer toBinaryString(b));



short s = 0x7fff. // макс шестнадцатеричное знач. short



printC's " + Integer.toBinaryString(s));



long nl = 200L; // Суффикс, обозначающий long



long n2 = 2001, // Суффикс, обозначающий long (можно запутаться)



long n3 = 200,



float fl = 1,



float f2 = IF; // Суффикс, обозначающий float float f3 = If, // Суффикс, обозначающий float double dl = Id, // Суффикс, обозначающий double double d2 = ID; // Суффикс, обозначающий double



}



} /* Output- il 101111 12 101111 13: 1111111 c: 1111111111111111 b: 1111111 s- 111111111111111 *///:-



Последний символ обозначает тип записанного литерала. Прописная или строчная буква L определяет тип long (впрочем, строчная I может создать про¬блемы, потому что она похожа на цифру 1); прописная или строчная F соответ¬ствует типу float, а заглавная или строчная D подразумевает тип double.



Шестнадцатеричное представление (основание 16) работает со всеми встро¬енными типами данных и обозначается префиксом Ох или ОХ с последующим числовым значением из цифр 0-9 и букв a-f, прописных или строчных. Если при определении переменной задается значение, превосходящее максимально для нее возможное (независимо от числовой формы), компилятор сообщит вам об ошибке. В программе указаны максимальные значения для типов char, byte и short. При выходе за эти границы компилятор автоматически сделает значе¬ние типом int и сообщит вам, что для присвоения понадобится сужающее при¬ведение.



Восьмеричное представление (по основанию 8) обозначается начальным ну¬лем в записи числа, состоящего из цифр от 0 до 7. Для литеральной записи чи¬сел в двоичном представлении в Java, С и С++ поддержки нет. Впрочем, при ра¬боте с шестнадцатеричныыми и восьмеричными числами часто требуется по¬лучить двоичное представление результата. Задача легко решается методами static toBinaryString() классов Integer и Long.



Экспоненциальная запись



Экспоненциальные значения записываются, по-моему, очень неудачно: 1.39e-47f. В науке и инженерном деле символом е обозначается основание натурального логарифма, равное примерно 2,718. (Более точное значение этой величины можно получить из свойства Math.E.) Оно используется в экспоненциальных выражениях, таких как 1,39хе-47, что фактически значит 1,39х2,718-47. Одна¬ко во время изобретения языка FORTRAN было решено, что е будет обозначать «десять в степени», что достаточно странно, поскольку FORTRAN разрабатывался для науки и техники и можно было предположить, что его создатели обратят внимание на подобную неоднозначность1. Так или иначе, этот обычай был пе¬ренят в С, С++, а затем перешел в Java. Таким образом, если вы привыкли ви¬деть в е основание натурального логарифма, вам придется каждый раз делать преобразование в уме: если вы увидели в Java выражение 1.39e-43f, на самом деле оно значит 1,39х10~43.



Если компилятор может определить тип автоматически, наличие завершаю¬щего суффикса типа не обязательно. В записи



long пЗ = 200;



не существует никаких неясностей, и поэтому использование символа L после значения 200 было бы излишним. Однако в записи



float f4 = le-43f; // десять в степени



компилятор обычно трактует экспоненциальные числа как double. Без завер¬шающего символа f он сообщит вам об ошибке и необходимости использования приведения для преобразования double к типу float.



Поразрядные операторы



Поразрядные операторы манипулируют отдельными битами в целочисленных примитивных типах данных. Результат определяется действиями булевой ал¬гебры с соответствующими битами двух операндов.



Эти битовые операторы происходят от низкоуровневой направленности языка С, где часто приходится напрямую работать с оборудованием и устанав¬ливать биты в аппаратных регистрах. Java изначально разрабатывался для управления телевизионными приставками, поэтому эта низкоуровневая ори¬ентация все еще была нужна. Впрочем, вам вряд ли придется часто использо¬вать эти операторы.



Поразрядный оператор И (&) заносит 1 в выходной бит, если оба входных бита были равны 1; в противном случае результат равен 0. Поразрядный опера¬тор ИЛИ (|) заносит 1 в выходной бит, если хотя бы один из битов операндов был равен 1; результат равен 0 только в том случае, если оба бита операндов были нулевыми. Оператор ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR, л) имеет результатом единицу тогда, когда один из входных битов был единицей, но не оба вместе. По¬разрядный оператор НЕ (~, также называемый оператором двоичного дополне¬ния) является унарным оператором, то есть имеет только один операнд. Пораз¬рядное НЕ производит бит, «противоположный» исходному — если входящий бит является нулем, то в результирующем бите окажется единица, если входя¬щий бит — единица, получится ноль.



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



Поразрядные операторы могут комбинироваться со знаком равенства =, что¬бы совместить операцию и присвоение: &=, |= и л= являются допустимыми соче¬таниями. (Так как ~ является унарным оператором, он не может использовать¬ся вместе со знаком =.)



Тип boolean трактуется как однобитовый, поэтому операции с ним выглядят по-другому. Вы вправе выполнить поразрядные И, ИЛИ и ИСКЛЮЧАЮЩЕЕ ИЛИ, но НЕ использовать запрещено (видимо, чтобы предотвратить путаницу с логическим НЕ). Для типа boolean поразрядные операторы производят тот же эффект, что и логические, за одним исключением — они не поддерживают уско¬ренного вычисления. Кроме того, в число поразрядных операторов для boolean входит оператор ИСКЛЮЧАЮЩЕЕ ИЛИ, отсутствующий в списке логиче¬ских операторов. Для булевых типов не разрешается использование операторов сдвига, описанных в следующем разделе.



Операторы сдвига



Операторы сдвига также манипулируют битами и используются только с при¬митивными целочисленными типами. Оператор сдвига влево («) сдвигает вле¬во операнд, находящийся слева от оператора, на количество битов, указанное после оператора. Оператор сдвига вправо (») сдвигает вправо операнд, находя¬щийся слева от оператора, на количество битов, указанное после оператора. При сдвиге вправо используется заполнение знаком: при положительном значе¬нии новые биты заполняются нулями, а при отрицательном — единицами. В Java также поддерживается беззнаковый сдвиг вправо »>, использующий за¬полнение нулями: независимо от знака старшие биты заполняются нулями. Та¬кой оператор не имеет аналогов в С и С++.



Если сдвигаемое значение относится к типу char, byte или short, эти типы приводятся к int перед выполнением сдвига, и результат также получится int. При этом используется только пять младших битов с «правой» стороны. Таким образом, нельзя сдвинуть битов больше, чем вообще существует для целого числа int. Если вы проводите операции с числами long, то получите результаты типа long. При этом будет задействовано только шесть младших битов с «пра¬вой» стороны, что предотвращает использование излишнего числа битов.



Сдвиги можно совмещать со знаком равенства («=, или »=, или »>=). Име¬нующее выражение заменяется им же, но с проведенными над ним операциями сдвига. Однако при этом возникает проблема с оператором беззнакового право¬го сдвига, совмещенного с присвоением. При использовании его с типом byte или short вы не получите правильных результатов. Вместо этого они сначала будут преобразованы к типу int и сдвинуты вправо, а затем обрезаны при воз¬вращении к исходному типу, и результатом станет -1. Следующий пример де¬монстрирует это:



//: operators/URShi ft java // Проверка беззнакового сдвига вправо, import static net.mindview.util Print *;



public class URShift {



public static void main(String[] args) { int i = -1;



print(Integer.toBinaryString(i)); i »>= 10;



print(Integer.toBinaryString(i)), long 1 = -1;



print(Long.toBinaryString(l)); 1 »>= 10;



print(Long.toBinaryString(l)); short s = -1;



printdnteger toBinaryString(s)); s »>= 10;



pri nt(Integer.toBi na ryStri ng(s)), byte b = -1;



printdnteger toBinaryString(b)); b »>= 10;



pri nt(Integer.toBi na ryString(b)); b = -1;



pri nt(Integer.toBi na rySt ring(b)), pri nt (I nteger. toBi narySt ri ng( b»>10));



}



} /* Output; 11111111111111111111111111111111 1111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 1111111111111111111111



В последней команде программы полученное значение не приводится обрат¬но к Ь, поэтому получается верное действие.



Следующий пример демонстрирует использование всех операторов, так или иначе связанных с поразрядными операциями:



//; operators/BitManipulation.java // Использование поразрядных операторов, import java.util.*;



import static net.mindview.util Print.*;



public class BitManipulation {



public static void main(String[] args) { Random rand = new Random(47);



int i = rand nextlntO, int j = rand.nextlntO. printBinarylntC'-l", -1); printBinarylntC'+l", +1); int maxpos = 2147483647; printBinaryInt("макс положит.", maxpos); int maxneg = -2147483648; printBinarylntC'MaKc отрицат.". maxneg); printBinarylntC'i". i); printBinaryInt("~i", ~i); printBinaryInt("-i", -i); printBinarylntC'j", j), printBinarylntC'i & j". i & j), printBinarylntC'i | j", i | j); printBinarylntC'i A j". i A j); printBinarylntC'i « 5", i «5); printBinarylntC'i » 5", i » 5): printBinarylntC'M) » 5", (~i) » 5); printBinarylntC'i »> 5", i »> 5); printBinarylntC'M) »> 5", (~i) »> 5);



long 1 = rand.nextLongO; long m = rand.nextLongO; printBinaryLong("-lL", -1L); printBinaryLong("+lL", +1L): long 11 = 9223372036854775807L, printBinaryLongC'MaKC. положит.", 11); long 1 In = -9223372036854775808L; printBinaryLongC'MaKC. отрицат ", lln); printBinaryLongC'l", 1); printBinaryLong("~l", -1), printBinaryLong("-l", -1), printBi naryLongC'm", m), printBinaryLongC'l & m", 1 & m); printBinaryLongC'l | m", 1 | m); printBinaryLongC'l A m", 1 A m); printBinaryLongC'l « 5", 1 «5); printBinaryLongC'l » 5". 1 » 5); printBinaryLong("(~l) » 5", (~1) » 5). printBinaryLongC'l »> 5". 1 »> 5); printBi naryLongC'H) »> 5", (~1) »> 5); moni tor.expect("Bi tMani pulati on.out");



}



static void printBinaryInt(String s, int i) {



print(s + ". int: " + i + двоичное: \n " + Integer toBinaryString(i));



}



static void printBinaryLong(String s, long 1) {



print(s + \ long: " + 1 + ", двоичное:\п " + Long.toBinaryStringd));



}



} /* Output-



-1, int- -1, двоичное.



11111111111111111111111111111111 +1, int. 1, двоичное. 1



макс, положит . int- 2147483647. двоичное: 1111111111111111111111111111111



макс, отрицат., int: -2147483648, двоичное- 10000000000000000000000000000000 i, int- -1172028779. двоичное: 10111010001001000100001010010101 ~i, int. 1172028778, двоичное. 1000101110110111011110101101010 -i, int. 1172028779. двоичное: 1000101110110111011110101101011 j. int: 1717241110, двоичное: 1100110010110110000010100010110 i & j, int- 570425364, двоичное: 100010000000000000000000010100 i | j, int. -25213033, двоичное. 11111110011111110100011110010111 i A j. int: -595638397, двоичное. 11011100011111110100011110000011 i «5, int: 1149784736, двоичное- 1000100100010000101001010100000 i » 5, int -36625900, двоичное. 11111101110100010010001000010100 (~i) » 5, int 36625899, двоичное. 10001011101101110111101011 i »> 5, int. 97591828, двоичное. 101110100010010001000010100 (~i) »> 5, int- 36625899, двоичное. 10001011101101110111101011



*///.-



Два метода в конце, printBinaryInt() и printBinaryl_ong(), получают в качестве параметров, соответственно, числа int и long и выводят их в двоичном формате вместе с сопроводительным текстом. Вместе с демонстрацией поразрядных опе¬раций для типов int и long этот пример также выводит минимальное и макси¬мальное значение, +1 и -1 для этих типов, чтобы вы лучше понимали, как они выглядят в двоичном представлении. Заметьте, что старший бит обозначает знак: 0 соответствует положительному и 1 — отрицательному числам. Резуль¬тат работы для типа int приведен в конце листинга

Report Page