Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Технологии обработки информации на Java. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
null-ссылка всегда может быть приведена к любому ссылочному ти-
пу путем расширяющей конверсии.
На практике программист может игнорировать null-тип и просто считать, что null – это такой специальный литерал, который можно при­своить любому ссылочному типу.
2.2. Примитивные Типы данных и Значения
Примитивные типы данных языка Java предопределены настоящей спецификацией, и в качестве имен им выделены ключевы
е слова:
ПримитивныйТип:
ЧисловойТип
boolean
ЧисловойТип:
ЦелочисленныйТип
ВещественныйТип
ЦелочисленныйТип: один из
byte short int long char
ВещественныйТип: один из
float double
Значения примитивных типов не могут иметь общего состояния с другими примитивными значениями.
Числовые типы делятся на целочисленные типы и вещественные ти­пы с плавающей точкой.
Целочисленные типы – это byte, short, int и long, чьи зна­чения – это, соответственно, 8-, 16-, 32- и 64-битные знаковые целые чис­ла, выраженные в дополненном коде, и char, чье значение – это 16-битное беззнаковое целое число, представляющее собой UTF-16 кодовый юнит.
Вещественные типы с плавающей точ
кой – это float, чье значение представляется в соответствии с требованиями на 32-битное вещественное число стандарта IEEE 754, и double, чье значение представляется в соответ­ствии с требованиями на 64-битное вещественное число стандарта IEEE 754.
Тип boolean имеет ровно два значения: true и false.
2.2.1. Цел
очисленные Типы и Значения
Значения целочисленных типов находятся в следующих диапазонах:
Для byte от -128 до 127 включительно.  Для short от -32768 до 32767 включительно.  Для int от -2147483648 до 2147483647 включительно.
11
Для long от -9223372036854775808 до -9223372036854775807
включительно.
Для char от '\u0000' до '\uffff', что в числах означает от 0 до
65535 включительно.
2.2.2. Операции над целочисленными значениями
Язык программирования Java предоставляет ряд операций, которые
могут выполняться над целочисленными значениями:
Операции сравнения, результатом которых является тип boolean: o операции числового сравнения <, <=, > и >= o операции числовой эквивалентности == и !=
Числовы
е операции, результатом которых является тип int или
long:
o унарный плюс и минус с использованием знаков + и – o мультипликативные операторы *, / и % o аддитивные операции + и – o операция инкремента ++ как в префиксной, так и в постфиксной
способах записи;
o операция декремента -- как в префиксной так и в постфиксной
способах записи;
o операции знакового и беззнакового побитов
ого сдвига <<, >>
и >>>
o операция побитового отрицания ~ o числовые побитовые операции &, ^ и |
Условная операция ? :  Операция приведения, которая может преобразовать значение це-
лочисленного типа к значению любого другого числового типа.
Операция строковой конкатенации +, которая выполняется в том
случае, если один из операндов имеет целочисленный тип, а другой имеет тип String. Эта о
перация преобразует числовой операнд к типу String (выражая число в десятичной системе счисления), и затем формирует но­вый объект типа String, который является конкатенацией ранее имев­шихся строк.
Другие полезные конструкторы, методы и константы определены
в классах Byte, Short, Integer, Long и Character.
Если любая числовая опер
ация, кроме операции побитового сдвига, имеет, по меньшей мере, один операнд типа long, тогда операция выпол­няется с 64-битной точностью, и результат числовой операции будет иметь тип long. В том случае, если второй оператор при этом имеет тип, отлич­ный от long, то перед выполнением операции он будет расшир
long путем выполнения числового приведения.
12
ен до типа
В том случае, если целочисленная операция имеет операнды любых других типов, кроме long, то операция выполняется с использованием 32-битной точности, а результатом выполнения числовой операции являет­ся тип int. Если любой из операндов имеет тип, отличный от int, то пе­ред выполнением операции он должен быть расширен до int путем вы­полнения числового приведения.
Любое значени
е любого целочисленного типа может быть преобра­зовано к любому числовому типу, и аналогично, значение любого числово­го типа можно привести к целочисленному типу. Однако невозможно про­извести преобразование между целочисленными типами и типом
boolean.
Числовые операции никоим образом не информируют о переполне-
нии или недополнении переменной.
Числов
ая операция может выбрасывать исключение в следующих
ситуациях:
Любая числовая операция может выбрасывать NullPointer
Exception в том случае, если для выполнения операции необходимо
произвести анбоксинг над ссылочной переменной, имеющей null в каче­стве значения.
Операция целочисленного деления / и операция получения остатка
от целочисленного деления % могут выбрасывать Arithmetic Exception в то
м случае, если их правосторонний операнд имеет нулевое
значение.
Операции инкремента и декремента ++ и -- могут выбрасывать
OutOfMemoryError в том случае, если при выполнении операции требу­ется выполнение боксинга, но в памяти JVM недостаточно места для со­здания нового объекта.
Пример 2.2.2-1. Числовые операции
Программа состоит из следующего модуля компиляции:
class Test { public static void main(String[] args) { int i = 1000000; System.out.println(i * i); long l = i; System.out.println(l * l); System.out.println(20296 / (l - i)); } }
В результате компиляции и выполнения данного кода на экран будет выведено
следующее:
-727379968 1000000000000
13
После чего на экране будет выведена информация о возникновении
ArithmeticException, так как в результатате вычисления выражения l-i, будет получен 0,
что приведет к ошибке целочисленного деления на ноль. Первое умножение выполня­ется с 32-битной точностью, в то время как второе умножение выполняется с 64-битной точностью. Значение -727379968 – это десятичное значение нижних 32 бит математи­ческого значения 1000000000000, которое слишком велико для представления в 32 би­тах типа int.
2.2.3. Вещественные Типы, Форматы и Значения
Вещественные типы с плавающей точкой – это float и double, кото­рые концептуально связаны с 32-битным форматом одинарной точности и 64-битным форматом двойной точности значений и операций так, как это указано в ANSI/IEEE стандарте 754-1985, IEEE Standard for Binary
Floating-Point Arithmetic, (IEEE, New York).
Стандарт IEEE 754 включает в себя не только положительные и от­рицательные числа, состоящие из знака и магнгитуды, но также положи­тельного и отрицательного нулей, положительной и отри
цательной беско­нечности и специального значения Не-Число (в англоязычной терминоло­гии Not-a-Number, в дальнейшем будет использоваться аббревиатура NaN). Значение NaN используется для представления результатов выполнения некорректной операции, такой, как деление нуля на ноль. Константа NaN для типов float и double доступна через классы-обертки: Float.NaN и Dou-
ble.NaN.
От каждой реализации языка программирования Java требуется под-
держка дв
ух стандартных наборов вещественных значений с плавающей точкой, называемых набор вещественных значений (float value set) и удво­енный набор вещественных значений (double value set). Кроме того, реали­зация языка программирования Java может поддерживать набор значений
с расширенной экспонентой (extended-exponent value set) и набор значений с удвоенно-расширенной экспонентой (double-extended-exponent value set).
Эти расширенные наборы значений могут, в конкретных обстоят
ельствах, быть использованы вместо стандартных наборов значений в выражениях типа float или double.
Конечное ненулевое значение, входящее в любой из этих наборов
K-1
(e-
-1
значений с вещественной точкой, может быть выражено в форме s*m*2
N+1)
, где s – это +1 или -1, m это положительное целое число меньшее, чем
N
; e – это целое число в диапазоне от E
2
min
= -(2
K-1
-2) – это E
max
=2
включительно, и где N и K – это параметры, которые зависят от конкретно используемого набора значений. Некоторые наборы могут быть представ­лены более чем одним способом. К примеру, предположим, что значение v в наборе значений может быть представлено в форме, использующей кон­кретные значения для s, m и e, тогда если m – это четное число, и e было
K-1
меньше че
м 2
, тогда m может быть сделано вдвое меньше и e увеличено
14
на 1, что позволяет создать второе представление для одного и того же значения v. Представление в такой форме называется нормализованным,
N-1
если m ≥ 2 значение в наборе значений не может быть представлено так, что m ≥ 2
; иначе представление называется денормализованным. Если
N-1
то такое значение называется денормализованным, т.к. оно не имеет нор­мализованного представления
и E
Ограничения параметров N и К (и унаследованных параметров E
) для двух обязательных и двух дополнительных наборов веществен-
max
min
ных значений суммированы в табл. 2.1.
Таблица 2.1
Параметры для наборов значений
Параметр вещественный с расширенной
экспонентой
N 24 24 53 53 K 8 ≥ 11 11 ≥ 15
E
+127 +1023 +1023 +16383
max
E
-126 -1022 -1022 -16382
min
удвоенный
вещественный
с удвоенно-расширенной
экспонентой
Если реализация языка поддерживает один или оба расширенных наборов значений, тогда для каждого поддерживаемого расширенного набора значений существует специфичная, зависящая от реализации кон­станта K, чье значение ограничивается табл. 2.1; это значение K, в свою очередь, указывает значения E
min
и E
max
.
Каждый из четырех наборов значений включает не только конечные ненулевые значения, описанные выше, но и значение NaN, а также и четы­ре специальных значения: положительный ноль, отрицательный ноль, по­ложительная бесконечность и отрицательная бесконечность.
Отметим, что ограничения в табл. 2.1 разработаны такими, что каж­дый элемент вещественного набора значений – это одновременно и значе­ние набора знач
ений с расширенной экспонентой, удвоенного набора ве­щественных значений и набора вещественных значений с удвоенно­расширенной экспонентой. По тому же принципу каждый элемент удвоен­ного набора вещественных значений – это одновременно и элемент набора вещественных значений с удвоенно-расширенной экспонентой. Каждый расширенный набор значений имеет больший диапазон значений экспо­нент, чем соответствующий стандартн
ый набор, но не может иметь боль-
шую точность.
Элементы вещественного набора значений – это в точности те значе­ния, которые могут быть представлены с использованием одной веще­ственной точки, определенной стандартом IEEE-754. Элементами удвоен­ного вещественного набора значений являются в точности те значения, ко­торые могут быть представлены с ис
пользованием одной удвоенной веще-
,
15
ственной точки, определенной стандартом IEEE-754. Отметим, однако, что элементы набора значений с расширенной экспонентой и набора значений с удвоенно-расширенной экспонентой, определенные здесь, не соответ­ствуют значениям, которые представляются с использованием стандарта на вещественные форматы с одинарной и двойной точностью стандарта IEEE-754 соответственно.
Вещественный, вещественный с расширенной экспонентой, удвоен­ный вещественный и вещественный с удвоенно-расширенн
ой экспонентой наборы значений не являются типами данных. Представление значений типа float в некоторой конкретной реализации языка Java может быть кор­ректно выполнено с использованием элементов вещественного набора зна­чений. Однако, в некоторых особенных частях кода для специфической ре­ализации языка Java вместо обычного набора значений может быть ис­пользован набор с расширенн
ой экспонентой. Точно таким же образом для представления типа double будет верным использование удвоенного набо­ра вещественных значений, но в некоторых частях кода специфическая ре­ализация языка Java может использовать набор значений с удвоенно­расширенной экспонентой вместо обычного.
Весь вещественный набор значений, за исклюлчением NaN, упоря-
дочен в порядке возрастания от наименьшего к наибольшему зн
ачению. Порядок следования значений следующий: начинается с отрицательной бесконечности, далее отрицательные конечные ненулевые значения, отри­цательный и положительный нули, затем конечные положительные нену­левые значения, и, наконец, положительная бесконечность.
Стандарт IEEE 754 допускает существование одновременно несколь­ких, различающихся между собой значений NaN для каждого из его фор­матов вещественных чисел, как обычных, так и удвоенных. Так же как и кажд
ая аппаратная платформа возвращает самостоятельно определенный битовый шаблон для значения NaN при его генерации, программист спо­собен самостоятельно задать значение NaN, пользуясь разными битовыми шаблонами, для отображения, к примеру, различной диагностической ин­формации.
По большей части, платформа Java SE считает значение NaN кон-
кретного типа свернутым в одно каноничное значени
е, и таким образом, данная спецификация обычно ссылается на NaN как на одно каноничное значение.
Однако, в версии 1.3 платформы Java SE были представлены методы, позволяющие программисту сделать различие между NaN значениями: Float.floatToRawIntBits и Double.doubleToRawLongBits. Заинтересованный читатель может обратиться к спецификации классов Float и Double для получения дополнительной информации.
Положительный ноль и отрицательный ноль с точки зрения срав­нения эквивалентны; таким образом, результат выражения 0.0 == -0.0 –
16
это true, а результат 0.0 > -0.0 – это false. Однако другие операции могут различать положительный и отрицательные нули; к примеру, выражение
1.0 / 0.0 в результате дает значение положительной бесконечности, а вы­ражение 1.0 / -0.0 в результате дает значение отрицательной бесконеч­ности.
Значение NaN неупорядоченно, поэтому:
Операции числового сравнения <, <=, > и >= возвращают false в том случае, если один или оба его операндов имеют значение NaN
(§15.20.1).
Операция эквивалентности == возвращает false в том случ
ае, если любой из операторов имеют значение NaN. В частности, (x<y)==!(x>=y) будет возвращать значение false в том случае, если x или y будут иметь значение NaN.
Оператор неравенства != возвращает true, если любой из операн-
дов имеет значение NaN. В частности, x!=x равен true тогда, когда x имеет значение NaN.
2.2.4. Операции над вещественными числами
Язык программирования Java предоставляет ряд операций, которые
могут выполняться над вещественными знач
ениями:
Операции сравнения, результатом которых является тип boolean:
o операции числового сравнения <, <=, > и >= o операции числовой эквивалентности == и !=
Числовые операции, результатом которых является тип float или
double:
o унарный плюс и минус с использованием операций + и o мультипликативные операторы *, / и % o аддитивные операц
ии + и –
o операция инкремента ++ как в префиксной, так и в постфиксной
способах записи;
o операция декремента -- как в префиксной так и в постфиксной
способах записи.
Условная операция ? :  Операция приведения, которая может преобразовать значение
вещественного типа к значению любого другого числового типа.
Операция строковой конкатенации +, которая выполняется в то
м случае, если один из операторов имеет вещественный тип, а другой имеет тип String, и преобразует числовой операнд к типу String, в десятичной форме (без потери информации), и затем формирует новый объект типа String, который является конкатенацией ранее имевшихся строк.
Другие полезные конструкторы, методы и константы определены
в классах Float, Double и Math.
17
Если любая бинарная числовая операция имеет, по меньшей мере, один операнд вещественного типа, тогда вся операция вычисляется с ис­пользованием вещественного типа, даже если один из операндов целочис­ленный.
Если любая числовая операция имеет, по меньшей мере, один опе­ранд типа double, тогда операция выполняется с использованием 64-битной вещественной арифметики, и результат число
вой операции будет иметь тип double. В том случае, если второй оператор при этом имеет тип, отлич­ный от double, то перед выполнением операции он будет расширен до типа double путем выполнения числового приведения.
В том случае, если вещественная операция имеет операнды любых других типов, кроме double, то операция выполняется с использованием 32-битной точности, а результатом выполнения числовой операции являет­ся тип float. Если любой из операндов имеет тип, отличный от float, то пе­ред выполнением операции он должен быть ра
сширен до float путем вы-
полнения числового приведения.
Любое значение любого вещественного типа может быть преобразо­вано к любому числовому типу и, аналогично, значение любого числового типа мож
но привести к вещественному типу. Однако невозможно произве-
сти преобразование между вещественными типами и типом boolean.
Поведение операций на вещественных числах подчиняется требо­ваниям стандарта IEEE 754 (за исключением операции получения остат­ка от деления). В частности, язык программирования Java требует под­держки денормализованных вещественных чисел стандарта IEEE 754 и gradual underflow, который упрощает подтверждение желаемых свойств конкретного числового алгоритма. Вещественные оп
ерации не используют «flush to zero», если вычисленный результат является де­нормализованным числом.
Язык программирования Java требует, чтобы вещественная арифме­тика вела себя так, как будто каждая вещественная операция округляет свой вещественный результат до требуемой точности. Неточный результат должен быть округлен до представимого значения, ближайшего к конеч­ному точному результату; если два ближайших представимых значени
я одинаково близки, то выбран должен быть тот, у которого наименьший значимый бит равен нулю. Это округление стандарта IEEE-754, использу­емое по умолчанию, и известное, как округление к ближайшему.
Язык программирования Java использует округление к нулю при конвертировании вещественного значения к целому числу, которое дей­ствует в этом случае так, как будто число было просто обрезано, откиды­вая биты мантиссы. Округление к нул
ю в качестве результата выбирает значение формата ближайшее и не большее по значению, чем бесконечно точный результат
18
Вещественная операция, результатом которой является переполне-
ние, будет возвращать знаковую бесконечность.
Вещественная операция, результатом которой является underflow,
будет возвращать денормализованное значение или знаковый ноль.
Не определенная математически вещественная операция возвращает
NaN.
Вещественная операция может выбрасывать исключение в следую-
щих ситуациях:
любая вещественная операция может выбрасывать NullPointerEx-
ception в том случае, если для выполнения операции необходимо п
роизве-
сти анбоксинг над null-ссылкой;
операции инкремента и декремента ++ и -- могут выбрасывать
OutOfMemoryError в том случае, если при выполнении операции требуется
выполнение боксинга, и в памяти JVM недостаточно места для создания нового объекта.
Пример 2.2.4-1. Вещественные операции
Программа состоит из следующего модуля компиляции:
class Test { public static void main(String[] args) { //пример переполнения: double d=1e308 System.out.print("переполнение возвращает бесконеч-
ность: ");
System.out.println(d + "*10==" + d*10); //пример gradual underflow: d=1e-305 * Math.PI; System.out.print("gradual underflow: " + d +"\n "); for (int i = 0; i < 4; i++) System.out.print(" " + (d /= 100000)); System.out.println(); // Пример получения NaN: System.out.print("0.0/0.0 это Не-Число: "); d = 0.0/0.0; System.out.println(d); // Пример неточного результата и округления: System.out.print("неточный результат с типом
float:");
for (int i = 0; i < 100; i++) { float z = 1.0f / i; if (z * i != 1.0f) System.out.print(" " + i); } System.out.println(); // Другой пример неточного результата и округления: System.out.print("неточный результат с типом
double:");
19
for (int i = 0; i < 100; i++) { double z = 1.0 / i; if (z * i != 1.0) System.out.print(" " + i); } System.out.println(); // Пример преобразования к целому числу с округле-
нием:
System.out.print("преобразование к int с округлени-
ем к 0: ");
d = 12345.6; System.out.println((int)d + " " + (int)(-d)); } }
результат компиляции и выполнения данного кода следующий:
переполнение возвращает бесконечность:
1.0e+308*10==Infinity gradual underflow: 3.141592653589793E-305
3.1415926535898E-310 3.141592653E-315 3.142E-320
0.0
0.0/0.0 это Не-Число: NaN неточный результат с типом float: 0 41 47 55 61 82
83 94 97
неточный результат с типом double: 0 49 98 преобразование к int с округлением к 0: 12345 -
12345
Этот пример демонстрирует, среди прочего, что в результате gradual underflow
может быть получено gradual loss of precision.
Результаты при i равном 0 включают в себя деление на ноль, так что z становит-
ся положительной бесконечностью, и z*0 это NaN, что не равно 1.0
2.2.5. Тип boolean и Логические Значения
Тип boolean представляет логическую величину с двумя возможны-
ми значениями, демонстрируемыми литералами true и false.
Логические операции – это:
Операции равенства и неравенства == и !=  Операция логического отрицания !  Логические операции &, ^ и |  Операции условное-И и условное-ИЛИ && и ||  Условная операция ? :  Операция строковой конкатенации +, которая выполняется в то
случае, если один из операторов имеет тип boolean, а другой имеет тип String, и преобразует boolean операнд к типу String (это будет строка либо "true" либо "false"), и затем формирует новый объект типа String, который является конкатенацией ранее имевшихся строк.
20
м
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]