Чем определяется точность представления чисел
Одинарная или двойная точность?
Введение
Статья также написана для тех из вас, у кого много данных. Если вам требуется несколько чисел тут или там, просто используйте double и не забивайте себе голову!
Точность данных
У 32-битных чисел с плавающей запятой точность примерно 24 бита, то есть около 7 десятичных знаков, а у чисел с двойной точностью — 53 бита, то есть примерно 16 десятичных знаков. Насколько это много? Вот некоторые грубые оценки того, какую точность вы получаете в худшем случае при использовании float и double для измерения объектов в разных диапазонах:
Почему всегда не хранить всё с двойной точностью?
Влияние на производительность вычислений с одинарной и двойной точностью
Когда производить вычисления с увеличенной точностью
Даже если вы храните данные с одинарной точностью, в некоторых случаях уместно использовать двойную точность при вычислениях. Вот простой пример на С:
Если вы запустите этот код на десяти числах одинарной точности, то не заметите каких-либо проблем с точностью. Но если запустите на миллионе чисел, то определённо заметите. Причина в том, что точность теряется при сложении больших и маленьких чисел, а после сложения миллиона чисел, вероятно, такая ситуация встретится. Практическое правило такое: если вы складываете 10^N значений, то теряете N десятичных знаков точности. Так что при сложении тысячи (10^3) чисел теряются три десятичных знака точности. Если складывать миллион (10^6) чисел, то теряются шесть десятичных знаков (а у float их всего семь!). Решение простое: вместо этого выполнять вычисления в формате double :
Пример
Предположим, что вы хотите точно измерить какое-то значение, но ваше измерительное устройство (с неким цифровым дисплеем) показывает только три значимых разряда. Измерение переменной десять раз выдаёт следующий ряд значений:
Чтобы увеличить точность, вы решаете сложить результаты измерений и вычислить среднее значение. В этом примере используется число с плавающей запятой в base-10, у которого точность составляет точно семь десятичных знаков (похоже на 32-битный float ). С тремя значимыми разрядами это даёт нам четыре дополнительных десятичных знака точности:
В сумме уже четыре значимых разряда, с тремя свободными. Что если сложить сотню таких значений? Тогда мы получим нечто вроде такого:
Всё ещё остались два неиспользованных разряда. Если суммировать тысячу чисел?
Пока что всё хорошо, но теперь мы используем все десятичные знаки для точности. Продолжим складывать числа:
Заметьте, как мы сдвигаем меньшее число, чтобы выровнять десятичный разделитель. У нас больше нет запасных разрядов, и мы опасно приблизились к потере точности. Что если сложить сто тысяч значений? Тогда добавление новых значений будет выглядеть так:
Обратите внимание, что последний значимый разряд данных (2 в 3.12) теряется. Вот теперь потеря точности действительно происходит, поскольку мы непрерывно будем игнорировать последний разряд точности наших данных. Мы видим, что проблема возникает после сложения десяти тысяч чисел, но до ста тысяч. У нас есть семь десятичных знаков точности, а в измерениях имеются три значимых разряда. Оставшиеся четыре разряда — это четыре порядка величины, которые выполняют роль своеобразного «числового буфера». Поэтому мы можем безопасно складывать четыре порядка величины = 10000 значений без потери точности, но дальше возникнут проблемы. Поэтому правило следующее:
(Существуют численно стабильные способы сложения большого количества значений. Однако простое переключение с float на double гораздо проще и, вероятно, быстрее).
Выводы
Приложение: Что такое число с плавающей запятой?
Я обнаружил, что многие на самом деле не вникают, что такое числа с плавающей запятой, поэтому есть смысл вкратце объяснить. Я пропущу здесь мельчайшие детали о битах, INF, NaN и поднормалях, а вместо этого покажу несколько примеров чисел с плавающей запятой в base-10. Всё то же самое применимо к двоичным числам.
Вот несколько примеров чисел с плавающей запятой, все с семью десятичными разрядами (это близко к 32-битному float ).
1.875545 · 10^-18 = 0.000 000 000 000 000 001 875 545
3.141593 · 10^0 = 3.141593
2.997925 · 10^8 = 299 792 500
6.022141 · 10^23 = 602 214 100 000 000 000 000 000
Выделенная жирным часть называется мантиссой, а выделенная курсивом — экспонентой. Вкратце, точность хранится в мантиссе, а величина в экспоненте. Так как с ними работать? Ну, умножение производится просто: перемножаем мантисссы и складываем экспоненты:
Сложение немного хитрее: чтобы сложить два числа разной величины, сначала нужно сдвинуть меньшее из двух чисел таким образом, чтобы запятая находилась в одном и том же месте.
Заметьте, как мы сдвинули некоторые из значимых десятичных знаков, чтобы запятые совпадали. Другими словами, мы теряем точность, когда складываем числа разных величин.
Чем определяется точность представления чисел
При решении различных задач требуется различная точность получаемых результатов. Так, при решении инженерных задач достаточна точность до 3—4 десятичных знаков (10—13 двоичных), при решении научных задач — 5—6 десятичных или 16—20 двоичных знаков и при решении особо точных задач — 8—9 десятичных, т. е. 25—30 двоичных разрядов.
При ограниченной длине машинных слов множество чисел, которые можно представить в машине, является конечным. Поэтому представление чисел в ЭВМ, как правило, влечет за собой появление погрешностей, величина которых зависит как от формы представления чисел, так и от длины разрядной сетки. Необходимо отметить, что запас точности в ЭВМ берется обычно в раза больше, чем это необходимо, что обусловлено кроме всего прочего накоплением погрешностей в ходе вычислений.
Точность представления числа характеризуется абсолютной и относительной погрешностями.
Абсолютная погрешность — это разность между истинным значением входной величины А и ее значением, полученным из машинного изображения т. е.
Усредненная абсолютная погрешность представления чисел в машинах с фиксированной запятой определяется как среднее арифметическое между минимально представимым числом и его минимальной потерей, е.
т. е. в машинах с фиксированной запятой абсолютная погрешность постоянна и равна половине младшего разряда.
Относительная погрешность представления определяется как отношение усредненной абсолютной погрешности к самому числу:
Так как само число А меняется в пределах
то и относительная погрешность является величиной переменной, меняющейся соответственно в пределах
Для машин с фиксированной запятой она определяется следующим образом:
Таким образом, относительная погрешность для машин с фиксированной запятой зависит от величины числа и колеблется в пределах для больших чисел, до
для малых чисел. Причем, при
относительная погрешность может достигать
В машинах с плавающей запятой абсолютная погрешность представления числа определяется следующим образом:
где — погрешность представления мантиссы, которая определяется так же, как абсолютная погрешность представления чисел в машине с фиксированной запятой, т. е.
— порядок числа, который изменяется в пределах
Следовательно, в отличие от машин с фиксированной запятой, в машинах с плавающей запятой абсолютная погрешность представления чисел зависит от порядка числа: минимальная при наибольшем отрицательном и максимальная при наибольшем положительном
определяются следующим образом:
Относительная погрешность представления чисел в машинах с плавающей запятой определяется по общему правилу:
т. е. к не зависит от порядка числа и изменяется в пределах
Следовательно, в машинах с плавающей запятой, в отличие от машины с фиксированной запятой, относительная погрешность изображения чисел во всем диапазоне представления практически постоянна и для чисел с нормализованной мантиссой зависит от количества разрядов мантиссы: чем их больше, тем меньше погрешность представления.
В некоторых вычислительных средствах информационной единицей являются не отдельные числа, а их блоки или массивы, т. е. последовательности, состоящие из сотен и тысяч чисел. В этих случаях нередко применяется промежуточная форма представления чисел в ЭВМ, так называемое представление с поблочно плавающей запятой, при котором всему массиву чисел присваивается общий порядок и массив считается нормализованным, если хотя бы одно его слово является нормализованным. Естественно, что относительная погрешность
представления отдельных элементов массива будет при этом различной. Как и в случае представления с фиксированной запятой, максимальный по абсолютной величине элемент будет представлен с минимальной, в то время как минимальный по абсолютной величине элемент массива — с максимальной относительной погрешностью. Однако это не имеет существенного значения, так как основную информационную нагрузку в этих случаях несут максимальные элементы массивов. Вместе с тем благодаря представлению чисел с поблочно плавающей запятой удается при приемлемой точности вычислений значительно сократить объем оборудования, а главное — время выполнения операции, так как действия над порядками в этом случае выполняются только один раз за время обработки всего массива чисел.
Из этого следует, что нельзя отдать предпочтение какой-либо одной форме представления чисел. Обычно в ЭВМ общего назначения применяют нормальную форму. Этим обеспечивается большой диапазон представления чисел, высокая точность вычислений, простота программирования. Усложнение аппаратуры этих ЭВМ имеет второстепенное значение,
В специализированных ЭВМ чаще применяют фиксированную или поблочно плавающую запятую, если информация обрабатывается отдельными массивами, так как эти формы обеспечивают простоту конструкции ЭВМ. Программа для этих ЭВМ составляется только один раз, диапазон изменения величин известен заранее, масштабные коэффициенты подбираются один раз, требуемая точность вычислений также известна заранее и определяет длину разрядной сетки.
В современных ЭВМ используются обе формы представления чисел. При этом в большинстве случаев формат чисел с фиксированной запятой служит для представления целых двоичных и десятичных чисел и выполнения операций над ними, что, например, необходимо для операций над кодами адресов (операции индексной арифметики).
В режиме с плавающей запятой обычно используется система счисления с основанием 16. В этом случае число А считается нормализованным, если хотя бы один из четырех старших двоичных разрядов отличен от 0. Это несколько уменьшает точность представления чисел, но позволяет резко увеличить диапазон представляемых в машине чисел и ускорить выполнение некоторых операций, в частности нормализации, так как сдвиг мантиссы производится сразу на 4 разряда. При этом каждый сдвиг мантиссы на 4 разряда влево или вправо требует соответствующего изменения порядка шестнадцатиричного числа всего лишь на единицу.
Точность представления в этом случае повышают за счет использования формата двойной длины (представление с удвоенной точностью).
Для упрощения действий над порядками в ЕС ЭВМ, например, их сводят к операциям над целыми положительными числами, используя представление чисел со смещенным порядком (смещение на ). Например, при семи разрядах, отводимых на представление порядка
плюс знаковый разряд),
Тогда порядки диапазона
будут ограничиваться пределами
что соответствует
Смещенные порядки называют характеристиками, чтобы не путать действительные и условные величины. Так как все характеристики являются положительными, то это упрощает выполнение некоторых действий над ними, например, сравнения. Для этого вычитание из одной характеристики другой можно производить без предварительного анализа их знаков.
Формы, диапазон и точность представления чисел
Как известно, в ЭВМ применяется двоичная система счисления. Может быть доказано, что при этом на построение ЭВМ тратится наименьшее количество базовых аппаратных элементов — «вентилей». Точнее, оптимальным основанием системы счисления по критерию «минимум аппаратных расходов» является основание натурального логарифма е= 2,72.
Однако по ряду очевидных причин для ЭВМ принято Р=2. Достаточно вспомнить, что одна из первых электронных ВМ ENIAC содержала 17 468 электронных ламп, имела размеры около 6 м в высоту и 30 м в длину. Обилие применяемых вакуумных ламп, габаритные размеры машины отчасти объяснялись тем, что она работала с десятичными числами.
Двоичные числа в компьютерах размещаются в ячейках памяти или в регистрах, которые состоят из запоминающих элементов — триггеров.
В ячейке или триггере хранится значение одного двоичного разряда — бит информации.
Разрядной сеткой компьютера называется совокупность запоминающих элементов для размещения одного двоичного числа. Для разных классов компьютеров длина разрядной сетки составляет 8, 16, 32, 64 и больше разрядов.
Форматом называется способ размещения компонентов числа в разрядной сетке, то есть последовательность и позиции знака, мантиссы, порядка и др.
Формы представления чисел
В компьютерах используются две формы представления числа:
• с фиксированной запятой перед старшим разрядом числа (для правильной дроби) или после младшего (для целого числа);
• с плавающей запятой, место положения которой задается порядком числа.
Место запятой в обоих форматах понимается неявно, без использования дополнительных разрядов. По традиции нумерация разрядов в больших машинах осуществляется слева направо, а в мини- и микрокомпьютерах и микропроцессорах— справа налево.
Представление вещественных чисел
Вещественные числа обычно представляются в виде чисел с плавающей запятой. Числа с плавающей запятой — один из возможных способов представления действительных чисел, который является компромиссом между точностью и диапазоном принимаемых значений, его можно считать аналогом экспоненциальной записи чисел, но только в памяти компьютера.
Число с плавающей запятой состоит из набора отдельных двоичных разрядов, условно разделенных на так называемые знак (англ. sign), порядок (англ. exponent) и мантиссу (англ. mantis). В наиболее распространённом формате (стандарт IEEE 754) число с плавающей запятой представляется в виде набора битов, часть из которых кодирует собой мантиссу числа, другая часть — показатель степени, и ещё один бит используется для указания знака числа ( [math]0[/math] — если число положительное, [math]1[/math] — если число отрицательное). При этом порядок записывается как целое число в коде со сдвигом, а мантисса — в нормализованном виде, своей дробной частью в двоичной системе счисления. Вот пример такого числа из [math]16[/math] двоичных разрядов:
Знак | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок | Мантисса | ||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
14 | 10 | 9 | 0 |
Знак — один бит, указывающий знак всего числа с плавающей точкой. Порядок и мантисса — целые числа, которые вместе со знаком дают представление числа с плавающей запятой в следующем виде:
Порядок также иногда называют экспонентой или просто показателем степени.
При этом лишь некоторые из вещественных чисел могут быть представлены в памяти компьютера точным значением, в то время как остальные числа представляются приближёнными значениями.
Более простым вариантом представления вещественных чисел является вариант с фиксированной точкой, когда целая и вещественная части хранятся отдельно. Например, на целую часть отводится всегда [math]X[/math] бит и на дробную отводится всегда [math]Y[/math] бит. Такой способ в архитектурах процессоров не присутствует. Отдаётся предпочтение числам с плавающей запятой, как компромиссу между диапазоном допустимых значений и точностью.
Содержание
Нормальная и нормализованная форма [ править ]
Типы чисел с плавающей точкой (по IEEE 754) [ править ]
Число половинной точности (Binary16, Half precision) [ править ]
Число́ полови́нной то́чности — компьютерный формат представления чисел, занимающий в памяти половину машинного слова (в случае 32-битного компьютера — [math]16[/math] бит или [math]2[/math] байта). В силу невысокой точности этот формат представления чисел с плавающей запятой обычно используется в видеокартах, где небольшой размер и высокая скорость работы важнее точности вычислений.
Знак | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок | Мантисса | |||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
14 | 10 | 9 | 0 |
Число одинарной точности (Binary32, Single precision, float) [ править ]
Число́ одина́рной то́чности — компьютерный формат представления чисел, занимающий в памяти одно машинное слово (в случае 32-битного компьютера — [math]32[/math] бита или [math]4[/math] байта). Используется для работы с вещественными числами везде, где не нужна очень высокая точность.
Знак | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок (8 бит) | Мантисса (23+1 бита) | |||||||||||||||||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
30 | 23 | 22 | 0 |
Число двойной точности (Binary64, Double precision, double) [ править ]
Число́ двойно́й то́чности — компьютерный формат представления чисел, занимающий в памяти два машинных слова (в случае 32-битного компьютера — [math]64[/math] бита или [math]8[/math] байт). Часто используется благодаря своей неплохой точности, даже несмотря на двойной расход памяти и сетевого трафика относительно чисел одинарной точности.
Знак | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок (11 бит) | Мантисса (52+1 бит) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
62 | 52 | 51 | 0 |
Число четверной точности (Binary128, Quadruple precision) [ править ]
Число́ четверно́й то́чности — компьютерный формат представления чисел, занимающий в памяти четыре машинных слова (в случае 32-битного компьютера — [math]128[/math] бит или [math]16[/math] байт). Используется в случае необходимости крайне высокой точности.
Знак | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок (15 бит) | Мантисса (112+1 бит) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
126 | 112 | 111 |
Мантисса (112+1 бит) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 |
Обычно этот формат реализуется программно, случаи аппаратной реализации крайне редки. Также не гарантируется поддержка этого типа в языках программирования, хотя кое-где она и реализована (например, компилятор gcc для архитектуры x86 позволяет использовать тип __float128, являющийся программной реализацией числа с четверной точностью). В совокупности эти факторы делают Quadruple весьма экзотичным и редко встречающимся форматом чисел с плавающей запятой.
Диапазон значений чисел с плавающей запятой [ править ]
Данная таблица только лишь примерно указывает границы допустимых значений, без учета возрастающей погрешности с ростом абсолютного значения и существования денормализованных чисел.
Особые значения чисел с плавающей точкой [ править ]
Ноль (со знаком) [ править ]
Как уже было оговорено выше, в нормализованной форме числа с плавающей точкой невозможно представить ноль. Поэтому для его представления зарезервированы специальные значения мантиссы и порядка — число считается нулём, если все его биты, кроме знакового, равны нулю. При этом в зависимости от значения бита знака ноль может быть как положительным, так и отрицательным.
Знак | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок | Мантисса | ||||||||||||||||
0 /1 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | = [math]\pm0[/math] |
14 | 10 | 9 | 0 |
Арифметика нуля со знаком
Арифметика отрицательного нуля аналогична таковой для любого отрицательного числа и понятна интуитивно. Вот несколько примеров:
Неопределенность (NaN) [ править ]
NaN — это аббревиатура от фразы «not a number«. NaN является результатом арифметических операций, если во время их выполнения произошла ошибка (примеры см. ниже). В IEEE 754 NaN представлен как число, в котором все двоичные разряды порядка — единицы, а мантисса не нулевая.
Знак | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок | Мантисса | ||||||||||||||||
0 /1 | 1 | 1 | 1 | 1 | 1 | 1, | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | = [math]NaN[/math] |
14 | 10 | 9 | 0 |
Любая операция с NaN возвращает NaN. При желании в мантиссу можно записывать информацию, которую программа сможет интерпретировать. Стандартом это не оговорено и мантисса чаще всего игнорируется.
Как можно получить NaN?
Есть и другие способы получения NaN, подробности можно найти по ссылкам в соответствующем разделе.
По определению NaN ≠ NaN, поэтому, для проверки значения переменной нужно просто сравнить ее с собой.
Бесконечности [ править ]
Знак | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Порядок | Мантисса | ||||||||||||||||
0 /1 | 1 | 1 | 1 | 1 | 1 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | = [math]\pm\infty[/math] |
14 | 10 | 9 | 0 |
Денормализованные числа [ править ]
То есть число с плавающей запятой, при учете вышесказанного, можно задать следующим образом:
В современных процессорах обработка денормализованных чисел происходит в десятки раз медленнее, чем обработка нормализованных чисел. Ниже приведена часть таблицы из статьи Isaac Dooley, Laxmikant Kale «Quantifying the Interference Caused by Subnormal Floating-Point Values» [1]
Производитель | Процессор | Замедление (разы) |
---|---|---|
IBM | PowerPC 970 | 2,4 |
AMD | Athlon | 6,0 |
Intel | Pentium 3 | 15,8 |
AMD | Athlon 64 | 21,4 |
AMD | Opteron64 | 23,8 |
Intel | Core Duo | 44,2 |
Intel | P4 Xeon | 97,9 |
Intel | Pentium 4 | 131,0 |
Intel | Itanium 2 | 183,2 |
Sun | UltraSPARC IV | 520,0 |
В таблице приведены наихудшие результаты тестирования среди всех использованных компиляторов (gcc, icc, xlc) со всеми доступными флагами оптимизации. Исследователи утверждают, что различие среднего случая с худшим незначительно.
Поскольку в стандартных форматах (одинарной и двойной точности) денормализованные числа получаются действительно очень маленькими и практически никак не влияют на результат некоторых вычислений (при этом заметно замедляя их скорость), то иногда они просто игнорируются. При этом используются два простых механизма, получивших называние Flush-to-zero (FTZ) и Denormals-are-zero (DAZ). Первый механизм заставляет операции возвращать ноль, как только становится ясно, что результат будет денормализованным. Второй механизм заставляет операции рассматривать поступающие на вход денормализованные числа как нули.
Ярким примером подобного «отсечения» денормализованных чисел могут послужить видеокарты, в которых резкое падение скорости вычислений в сотню раз недопустимо. Так же, например, в областях, связанных с обработкой звука, нет нужды в очень маленьких числах, поскольку они представляют столь тихий звук, что его не способно воспринять человеческое ухо.
В версии стандарта IEEE 754-2008 денормализованные числа (denormal или denormalized numbers) были переименованы в subnormal numbers, то есть в числа, меньшие «нормальных». Поэтому их иногда еще называют «субнормальными«.
Действия с числами с плавающей запятой [ править ]
Умножение и деление [ править ]
Самыми простыми для восприятия арифметическими операциями над числами с плавающей запятой являются умножение и деление. Для того, чтобы умножить два вещественных числа в нормализованной форме необходимо перемножить их мантиссы, сложить порядки, округлить и нормализовать полученное число.
Соответственно, чтобы произвести деление нужно разделить мантиссу делимого на мантиссу делителя и вычесть из порядка делимого порядок делителя. Затем точно так же округлить мантиссу результата и привести его к нормализованной форме.
Сложение и вычитание [ править ]
Идея метода сложения и вычитания чисел с плавающей точкой заключается в приведении их к одному порядку. Сначала выбирается оптимальный порядок, затем мантиссы обоих чисел представляются в соответствии с новым порядком, затем над ними производится сложение/вычитание, мантисса результата округляется и, если нужно, результат приводится к нормализированной форме. Пример:
Алгоритм получения представления вещественного числа в памяти ЭВМ [ править ]
Покажем преобразование действительного числа для представления его в памяти ЭВМ на примере величины типа Double.
Как видно из таблицы, величина этого типа занимает в памяти [math]8[/math] байт. На рисунке ниже показано, как здесь представлены поля мантиссы и порядка (нумерация битов осуществляется справа налево):
Знак | Смещённый порядок | Мантисса |
---|---|---|
63 | 62..52 | 51..0 |
Таким образом, из вышесказанного вытекает следующий алгоритм для получения представления действительного числа в памяти ЭВМ:
Очевидно, что более компактно полученный код стоит записать следующим образом: C073850000000000(16).
Другой пример иллюстрирует обратный переход от кода действительного числа к самому числу.
Пример. Пусть дан код 3FEC600000000000(16) или
0 | 01111111110 | 1100011000000000000000000000000000000000000000000000 |
63 | 62..52 | 51..0 |