Смекни!
smekni.com

Общие представления о языке Java 5 (стр. 29 из 68)

Но значение Ind вообще не употребляется и отождествляется с NaN, хотя Float.NaN и Double.NaN различаются.

Числа в формате с плавающей точкой занимают следующие диапазоны значений:

Название значения s (знак) p (порядок) m (мантисса)
-NaN (отрицательное не-число) 1 11..11 11..11 : 10..01
Indeterminate (неопределённость) 1 11..11 10..00
Signaling -NaN (отрицательное не-число, возбуждающее ошибку) 1 11..11 01..11 : 00..01
-Infinity (отрицательное переполнение, плюс бесконечность) 1 11..11 00..00
Отрицательное нормализованное 1 11..10 : 00..01 11..11 : 00..00
Отрицательное ненормализованное 1 00..00 11..11 : 00..01
-0 1 00..00 00..00
+0 0 00..00 00..00
Положительное ненормализованное 0 00..00 00..01 : 11..11
Положительное нормализованное 0 00..01 : 11..10 00..00 : 11..11
+Infinity (положительное переполнение, плюс бесконечность) 0 11..11 00..00
Signaling +NaN (положительное не-число, возбуждающее ошибку) 0 11..11 00..01 : 01..11
Quiet +NaN (положительное не-число) 0 11..11 10..00 : 11..11

Имеются методы оболочечных классов, позволяющие преобразовывать наборы бит, хранящихся в ячейках типа int, в значения float, и наоборот – значения типа float в их битовое представление типа int. При этом содержание ячеек не меняется – просто содержащиеся в ячейках наборы бит начинают по-другому трактоваться.

Аналогичные операции существуют и для значений типа long и double:

Float.intBitsToFloat(значение типа int)

Double.longBitsToDouble(значение типа long)

Float.floatToIntBits(значение типа float)

Double.doubleToLongBits(значение типа double)

Например, Float.intBitsToFloat(0x7F7FFFFF) даст значение, равное Float.MAX_VALUE, Float.intBitsToFloat(0x7F800000) – значение Float.POSITIVE_INFINITY,

Float.intBitsToFloat(0xFF800000) – значение Float.NEGATIVE_INFINITY.

Если аргумент метода Float.intBitsToFloat лежит в пределах от 0xF800001 до 0xF800001, результатом будет Float.NaN.

Следует подчеркнуть, что данные операции принципиально отличаются от “обычных” преобразований типов, например, из int в float или из double в long. При “обычных” преобразованиях значение числа не меняется, просто меняется форма хранения этого значения и, соответственно, наборы битов, которыми кодируется это значение. Причём может измениться размер ячейки (скажем, при преобразовании значений int в значения double). А при рассматриваемых в данном разделе операциях сохраняется набор бит и размер ячейки, но меняется тип, который приписывается этому набору.

Краткие итоги по главе 4

- Отрицательные целые числа кодируются в дополнительном коде.

- При сложении, вычитании и, особенно, умножении целых чисел может возникать выход за пределы допустимого диапазона. В результате у результата может получиться значение, имеющее противоположный по сравнению с правильным результатом знак. Или нуль при сложении чисел одного знака.

- Побитовая маска AND (оператор “&”) служит для сбрасывания в 0 тех битов числа, где в маске стоит 0, остальные биты числа не меняются. Побитовая маска OR (оператор “|”) служит для установки в 1 тех битов числа, где в маске стоит 1, остальные биты числа не меняются.

- Побитовая маска XOR (оператор “^”) служит для инверсии тех битов числа, где в маске стоит 1 (единицы переходят в нули, а нули – в единицы), остальные биты числа не меняются. Имеется команда перевода вывода графики в режим XOR при рисовании, для этого используется команда graphics.setXORMode(цвет).

- Инверсия всех битов числа осуществляется с помощью побитового отрицания ~a.

- Побитовые сдвиги “<<”, “>>” и “>>>” приводят к перемещению всех бит ячейки, к которой применяется оператор, на указанное число бит влево или вправо. Причём m<<n является очень быстрым вариантом операции m∙2n, а m>>n – целочисленному делению m на 2n.

- Литерные константы для вещественных типов по умолчанию имеют тип double. Например, 1.5 , -17E2 , 0.0 . Если требуется ввести литерную константу типа float, после записи числа добавляют постфикс f (сокращение от “float”): 1.5f , -17E2f , 0.0f .

- Число в формате с плавающей точкой состоит из знакового бита, мантиссы и порядка. Все операции с числами такого формата сопровождаются накоплением ошибки порядка нескольких младших битов мантиссы ненормализованного результата.

- При проведении умножения и деления чисел в формате с плавающей точкой не происходит катастрофической потери точности результата. А при сложениях и вычитаниях такая потеря может происходить в случае, когда вычисляется разность двух значений, к которым прибавляется малая относительно этих значений добавка. Число порядков при потере точности равно числу порядков, на которые отличаются эти значения от малой добавки.

Типичные ошибки:

  • При использовании целых типов не знают или забывают, что при выходе за пределы диапазона соответствующие биты отбрасываются без всякой диагностики переполнения. И что получившийся результат может быть неправильного знака или нуль. Особенно часто переполнение возникает при умножении нескольких целых величин друг на друга.
  • Написание численных алгоритмов с катастрофической потерей точности.
  • Сравнение двух чисел в формате с плавающей точкой на равенство или неравенство в случае, когда в точной арифметике они должны быть равны.

Задания

  • Создать проект с графическим пользовательским интерфейсом, в котором имеется два пункта ввода и радиогруппа с выбором варианта для каждого из целочисленных типов, а также кнопки JButton с надписями “Сложить” и “Умножить”. При выборе соответствующего варианта в пунктах ввода должны возникать случайным образом генерируемые числа, лежащее в пределах допустимых значений для этого типа. При нажатии на кнопку содержимое пунктов ввода и результат действий должны быть преобразованы в значения соответствующего типа, и результат выполнения сложения или умножения должен быть показан в метке. Проверить наличие проблемы арифметического переполнения для разных значений каждого типа. Выяснить, в каком случае чаще происходит переполнение – при сложении или умножении. И насколько часто встречаются такие значения одного знака, чтобы в результате получился результат противоположного знака. Вручную ввести в пункты ввода такие значения одного знака, чтобы в результате получилось нулевое значение.
  • Написать приложение с графическим пользовательским интерфейсом, в котором вычисляется выражение 1+x и присваиваются переменной float f, а также вычисляется выражение 1+y и присваиваются переменной double d. Величины x типа float и y типа double вводится пользователем с помощью пунктов ввода. Вывести в метку jLabel1 разность f-1 , и в метку jLabel2 разность d-1 . Провести вычисления для x и y, меняющихся в пределах от 1E-3 до 1E-18 . Объяснить результаты.
  • * Для студентов технических вузов и физико-математических факультетов университетов. Написать приложение с графическим пользовательским интерфейсом, в котором вычисляются выражения f1(x) и f2(x), где f1(x)=a(x)-b(x), a(x)=ex, b(x)=1+x, и f2(x)=
    . Поскольку f2(x) состоит из первых членов разложения f1(x) в ряд, то f1(x) и f2(x) должны быть примерно равны . Требуется сравнить значения выражения f1(x) и f2(x) при различных x. Все вычисления сначала проводить для переменных и функций типа float, а затем - для переменных и функций типа double. Величина x вводится пользователем. Вывести в метки значения f1_double (x), a_double(x), b_double(x), f1_float(x), a_float(x), b_float(x), а также разности f1_float(x)-f2_float(x) и f1_double (x) - f2_double (x). Провести такое сравнение для аргументов x, меняющихся в пределах от 1E-8 до 0.1. Объяснить результаты.

Глава 5. Управляющие конструкции

Составной оператор

Согласно синтаксису языка Java во многих конструкциях может стоять только один оператор, но часто встречается ситуация, когда надо использовать последовательность из нескольких операторов.

Составной оператор — блок кода между фигурными скобками {}:

Имеется два общепринятых способа форматирования текста с использованием фигурных скобок.

В первом из них скобки пишут друг под другом, а текст, находящийся между ними, сдвигают на 1-2 символа вправо (изредка – больше). Пример:

оператор

{

последовательность простых или составных операторов

}

Во втором, более распространённом, открывающую фигурную скобку пишут на той же строке, где должен начинаться составной оператор, без переноса его на следующую строку. А закрывающую скобку пишут под первым словом. Пример:

оператор{

последовательность простых или составных операторов

}

Именно такой способ установлен по умолчанию в среде NetBeans, и именно он используется в приводимых в данной книге фрагментах программного кода. Тем не менее, автор предпочитает первый способ форматирования программного кода, так как он более читаемый. Для установки такого способа форматирования исходного кода следует перейти в меню Tools/Options, выбрать Editor/Indentation, после чего в появившейся диалоговой форме отметить галочкой пункт Add New Line Before Brace.

После фигурных скобок по правилам Java, как и в /C++, ставить символ “;” не надо. Но его можно ставить после фигурных скобок в тех местах программы, где разрешается ставить ничего не делающий пустой оператор “;” .

Условный оператор if

У условного оператора if имеется две формы: if и if- else.