8-900-374-94-44
[email protected]
Slide Image
Меню

С плавающей точкой операции: Что нужно знать про арифметику с плавающей запятой / Хабр

Наглядное объяснение чисел с плавающей запятой / Хабр

В начале 90-х создание трёхмерного игрового движка означало, что вы заставите машину выполнять почти не свойственные ей задачи. Персональные компьютеры того времени предназначались для запуска текстовых процессоров и электронных таблиц, а не для 3D-вычислений с частотой 70 кадров в секунду. Серьёзным препятствием стало то, что, несмотря на свою мощь, ЦП не имел аппаратного устройства для вычислений с плавающей запятой. У программистов было только АЛУ, перемалывающее целые числа.

При написании книги Game Engine Black Book: Wolfenstein 3D я хотел наглядно показать, насколько велики были проблемы при работе без плавающей запятой. Мои попытки разобраться в числах с плавающей запятой при помощи каноничных статей мозг воспринимал в штыки. Я начал искать другой способ. Что-нибудь, далёкое от и их загадочных экспонент с мантиссами. Может быть, в виде рисунка, потому что их мой мозг воспринимает проще.

В результате я написал эту статью и решил добавить её в книгу. Не буду утверждать, что это моё изобретение, но пока мне не приходилось видеть такого объяснения чисел с плавающей запятой. Надеюсь, статья поможет тем, у кого, как и у меня, аллергия на математические обозначения.

Как обычно объясняют числа с плавающей запятой

Цитирую Дэвида Голдберта (David Goldbert):

Для многих людей арифметика с плавающей запятой кажется каким-то тайным знанием.

Полностью с ним согласен. Однако важно понимать принципы её работы, чтобы полностью осознать её полезность при программировании 3D-движка. В языке C значения с плавающей запятой — это 32-битные контейнеры, соответствующие стандарту IEEE 754. Они предназначены для хранения и выполнения операций над аппроксимациями вещественных чисел. Пока я видел только такое их объяснение. 32 бита разделены на три части:

  • S (1 бит) для хранения знака
  • E (8 бит) для экспоненты
  • M (23 бита) для мантиссы

Внутренности числа с плавающей запятой.


Три части числа с плавающей запятой.

Пока всё нормально. Пойдём дальше. Способ интерпретации чисел обычно объясняется с помощью такой формулы:

Именно это объяснение чисел с плавающей запятой все ненавидят.

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

Другой способ объяснения

Хоть это изложение и верно, такой способ объяснения чисел с плавающей запятой обычно не даёт нам никакого понимания. Я виню эту ужасную запись в том, что она разочаровала тысячи программистов, испугала их до такой степени, что они больше никогда не пытались понять, как же на самом деле работают вычисления с плавающей запятой. К счастью, их можно объяснить иначе. Воспринимайте экспоненту как окно (Window) или интервал между двумя соседними целыми степенями двойки.

Мантиссу воспринимайте как смещение (Offset) в этом окне.


Три части числа с плавающей запятой.

Окно сообщает нам, между какими двумя последовательными степенями двойки будет число: [0,1], [1,2], [2,4], [4,8] и так далее (вплоть до [,]. Смещение разделяет окно на сегментов. С помощью окна и смещения можно аппроксимировать число. Окно — это отличный механизм защиты от выхода за границы. Достигнув максимума в окне (например, в [2,4]), можно «переплыть» вправо и представить число в пределах следующего окна (например, [4,8]). Ценой этого будет только небольшое снижение точности, потому что окно становится в два раза больше.

Викторина: сколько точности теряется, когда окно закрывает больший интервал? Давайте возьмём пример с окном [0,1], в котором 8388608 смещений накладываются на интервал размером 1, что даёт нам точность . В окне [2048,4096] 8388608 смещений накладываются на интервал , что даёт нам точность .

На рисунке ниже показано, как кодируется число 6,1. Окно должно начинаться с 4 и заканчиваться следующей степенью двойки, т.е. 8. Смещение находится примерно посередине окна.


Значение 6,1 аппроксимированное с помощью числа с плавающей запятой.

Давайте возьмём ещё один пример с подробным вычислением представлением в виде числа с плавающей точкой хорошо известного всем нам значения: 3,14.

  • Число 3,14 положительно .
  • Число 3,14 находится между степенями двойки 2 и 4, то есть окно числа с плавающей запятой должно начинаться с (см. формулу, где окно — это ).
  • Наконец, есть смещений, которыми можно выразить расположение 3,14 внутри интервала [2-4]. Оно находится в внутри интервала, что даёт нам смещение

В двоичном виде это преобразуется в следующее:

  • S = 0 = 0b
  • E = 128 = 10000000b
  • M = 4781507 = 10010001111010111000011b

Двоичное представление с плавающей точкой числа 3,14.

То есть значение 3,14 аппроксимируется как 3,1400001049041748046875.

Соответствующее значение в непонятной формуле:

И, наконец, графическое представление с окном и смещением:

Окно и смещение числа 3,14.

Интересный факт: если модули операций с плавающей запятой были такими медленными, почему в языке C в результате использовали типы float и double? Ведь в машине, на которой изобретался язык (PDP-11), не было модуля операций с плавающей запятой! Дело в том, что производитель (DEC) пообещал Деннису Ритчи и Кену Томпсону, что в следующей модели он будет. Они были любителями астрономии и решили добавить в язык эти два типа.

Интересный факт: те, кому в 1991 году действительно нужен был аппаратный модуль операций с плавающей запятой, могли его купить. Единственными, кому он мог понадобиться в то время, были учёные (по крайней мере, так Intel понимала потребности рынка). На рынке они позиционировались как «математические сопроцессоры». Их производительность была средней, а цена огромной (200 долларов 1993 года — это 350 долларов в 2016 году.). В результате уровень продаж оказался посредственным.

Надеюсь, статья была вам полезна!

НОУ ИНТУИТ | Лекция | Арифметические операции над числами с плавающей запятой

Аннотация: Цель лекции: определить структуру числа с плавающей запятой, особенности его представления в соответствии с ГОСТ IEEE 754, порядок выполнения умножения, деления сложения и вычитания чисел с плавающей запятой, особые ситуации, возникающие при выполнении этих операций и способы обработки этих ситуаций. Ключевые слова: число с плавающей запятой, ГОСТ IEEE 754, особые ситуации при обработке чисел с плавающей запятой.

Формат числа с плавающей запятой

Число с плавающей запятой представляется в виде мантиссы (М) и порядка (П).

Например, число А = 123 может быть представлено в виде числа с мантиссой 12,3 и порядком +1, то есть 12,3 *10+1.

Другие представления этого самого же числа могут выглядеть так: 123 = 123*100 = 1230 10-1 = 0,123*10+3 = 0, 0123 * 10+4 = …

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

Нормализованная мантисса должна удовлетворять условию:

( 10.1)

где р – основание системы счисления, то есть мантисса представляет собой правильную дробь, у модуля которой старшая цифра отлична от нуля.

Из приведенного выше примера этому условию удовлетворяет лишь запись

intuit.ru/2010/edi»>А = 0,123*10+3

Как мантисса, так и порядок могут быть как положительными, так и отрицательными числами. Поэтому в общем виде число с плавающей запятой имеет следующий формат (Рис. 10.1). В дальнейшем мы рассмотрим, как форма кодирования чисел в ЭВМ сказывается на этом формате. В этой лекции будем исходить именно из такой формы представления числа с плавающей запятой, так как она позволяет выявить все особенности обработки таких чисел.

Рис. 10.1. Структура числа с плавающей запятой

Порядок представляет собой число с фиксированной точкой, мантисса – число с фиксированной запятой. Поэтому:

Ммакс = 0,1 … 1 = 1-2-n

Ммин = 2-1 (напомним, что мантисса должна быть нормализована).

Пмакс = 0,1 … 1 = 2m-1

макс = -(2m-1)

Мы пока ведем речь только о естественном, а не машинном представлении числа, где, например, в так называемом дополнительном коде можно представить на одну комбинацию отрицательных чисел больше, чем положительных.

В данном случае достаточно просто определить диапазон представляемых чисел

Абсолютная погрешность представления числа с плавающей запятой ЭВМ составит:

Относительная погрешность представления в ЭВМ числа с плавающей запятой будет равна:

Таким образом, мы видим, что для чисел с плавающей запятой диапазон их представления весьма широк и определяется в основном, количеством разрядов, отводимых под порядок числа, а относительная погрешность меняется гораздо меньше, чем для чисел с фиксированной точкой (всего в 2 раза) и определяется количеством разрядов, отводимых под запись мантиссы числа.

Умножение чисел с плавающей запятой

Сначала рассмотрим случай перемножения двух чисел с плавающей запятой в десятичной системе счисления.

(0,3*103) * (0,2*102) = (0,3 * 0,2) *103+2 = 0,06 * 105 = 0,6* 104

Последний шаг выполнен для нормализации мантиссы результата.

Таким образом, если представить операнды в двоичной системе счисления как

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

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

intuit.ru/2010/edi»>Пz = Пx + Пy

Mz = Mx * My

Интерес здесь представляют особые случаи, которые могут возникнуть на различных этапах обработки числа. Так при сложении чисел с фиксированной точкой (речь идёт о порядках) может возникнуть переполнение, которое сделает невозможным дальнейшую работу с этим числом, либо при перемножении мантисс сомножителей мы получим денормализованную мантиссу результата, что потребует ее коррекции с одновременной коррекцией полученного ранее порядка произведения. Все эти и некоторые другие обстоятельства необходимо учитывать при проведении данной операции.

Ряд этих случаев будем рассмотрен нами при обсуждении ГОСТа IEEE 754 на представление чисел с плавающей запятой [ …]. В то же время иногда подобные ситуации возникают в процессе выполнения самой операции, а окончательный результат оказывается допустимым числом. Рассмотрим все эти случаи.

Особые случаи при умножении чисел с плавающей запятой

Главное обстоятельство, на которое следует обратить внимание при умножении чисел с плавающей запятой, это диапазон мантисс, которые получаются при выполнении операции.

Так как мы исходим из того, что мантиссы обоих операндов нормализованы, то есть удовлетворяют условию

1 > |Mx,y| ≥ 2-1,

то 1 > |Mz| = |Mx| * |My| ≥ 2-2.

Таким образом, нормализация мантиссы если и потребуется, то только путем сдвига на один разряд влево. При этом порядок, естественно, следует уменьшить на 1. Отсюда вытекает следующая последовательность действий.

  1. Пz = Пx + Пy
    1. Если Пz = — ∞, то Z=0 .
    2. Если Пz = + ∞, то продолжить умножение, так как последующая операция над мантиссами может привести к коррекции порядка результата в сторону его уменьшения и, тем самым, обеспечит нормальное представление числа в целом.
  2. Mz = Mx * My

Т.к. |Mx| ≥ 2-1, |My| ≥ 2-1, то |Mz| ≥ 2-2

Возможная область ненормализованной мантиссы:

2-1 > |Mz| ≥ 2-2

Если |Mz| < 2-1, то выполнить нормализацию мантиссы с одновременной коррекцией порядка:

|Mz| = |Mz| * 2+1

Пz = Пz -1

intuit.ru/2010/edi»>Если в результате получим Пz = — ∞, то Z=0.

Если в ходе перемножения мантисс получим |Mz| ≥ 2-1 , но ранее при обработке порядков получили Пz = + ∞ (см п.1.2), то Z = ∞

При Z=0 выполнение программы в ЭВМ продолжается.

При Z = ∞ устанавливается флаг прерывания, и ЭВМ приостанавливает обработку данных чисел.

404: Страница не найдена

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

Что я могу сделать сейчас?

Если вы впервые посещаете TechTarget, добро пожаловать! Извините за обстоятельства, при которых мы встречаемся. Вот куда вы можете пойти отсюда:

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

Просмотр по категории

Сеть

  • основная полоса

    Основная полоса при передаче сигналов связи означает, что для отправки и приема цифровых сигналов доступен только один путь …

  • широкополосный

    Широкополосный доступ относится к телекоммуникациям, в которых для передачи информации доступна широкая полоса частот.

  • оптоволокно до дома (FTTH)

    Оптоволокно до дома (FTTH), также называемое оптоволокном до помещения (FTTP), представляет собой установку и использование оптического волокна от центрального …

Безопасность

  • Общая система оценки уязвимостей (CVSS)

    Общая система оценки уязвимостей (CVSS) — это общедоступная платформа для оценки серьезности уязвимостей безопасности в . ..

  • WPA3

    WPA3, также известный как Wi-Fi Protected Access 3, является третьей итерацией стандарта сертификации безопасности, разработанного Wi-Fi …

  • брандмауэр

    Брандмауэр — это устройство сетевой безопасности, предотвращающее несанкционированный доступ к сети. Проверяет входящий и исходящий трафик…

ИТ-директор

  • Agile-манифест

    The Agile Manifesto — это документ, определяющий четыре ключевые ценности и 12 принципов, в которые его авторы верят разработчикам программного обеспечения…

  • Общее управление качеством (TQM)

    Total Quality Management (TQM) — это система управления, основанная на вере в то, что организация может добиться долгосрочного успеха, …

  • системное мышление

    Системное мышление — это целостный подход к анализу, который фокусируется на том, как взаимодействуют составные части системы и как. ..

HRSoftware

  • непрерывное управление производительностью

    Непрерывное управление эффективностью в контексте управления человеческими ресурсами (HR) представляет собой надзор за работой сотрудника …

  • вовлечения сотрудников

    Вовлеченность сотрудников — это эмоциональная и профессиональная связь, которую сотрудник испытывает к своей организации, коллегам и работе.

  • кадровый резерв

    Кадровый резерв — это база данных кандидатов на работу, которые могут удовлетворить немедленные и долгосрочные потребности организации.

Обслуживание клиентов

  • бесконтактная оплата

    Бесконтактный платеж — это беспроводная финансовая транзакция, при которой покупатель совершает покупку, перемещая токен безопасности в …

  • исходящий вызов

    Исходящий вызов — это вызов, инициированный оператором центра обработки вызовов клиенту от имени центра обработки вызовов или клиента.

  • социальная CRM

    Social CRM, или социальное управление взаимоотношениями с клиентами, — это управление взаимоотношениями с клиентами и взаимодействие с ними, поддерживаемое …

Потеря точности: советы по работе со сложными арифметическими операциями с плавающей запятой

Мэри Пэт Кэмпбелл

У вас открыт Excel? Поместите это в A1:

=1*(.5-.4-.1)

Что вы получили? Если вы получили ноль, попробуйте попросить Excel показать вам больше цифр после запятой. Однако, как правило, Excel по умолчанию возвращается к следующей нотации с плавающей запятой:

-2.78E-17

Конечно, это мало, но не ноль.

Отдельно, если вы посмотрите мою таблицу из январского выпуска журнала CompAct за 2014 год, сопровождающую статью под названием «Вариации приближения — исследование в расчетах», вы увидите, что на некоторых вкладках кумулятивная сумма вероятностей для аппроксимированное биномиальное распределение меньше 1 (примерно на 10 ^ -14). Это может вызвать у нас проблемы с некоторыми приложениями дистрибутива. Вычисленные числа должны в сумме давать единицу, по крайней мере, для вкладок, не использующих приближения, если бы мы использовали точную арифметику, карандаш и бумагу. Но в Excel этого не будет.

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

Во-первых, что такое представление вещественного числа с плавающей запятой? Это выглядит так:

(+/-) Значимая* основа Показатель степени

Стандартные формы обычно заставляют эту «значащую» часть быть между 0,0 и 9.999999 (до уровня точности станка). База будет указана (обычно две для компьютеров). Каждая система будет иметь ограничения на количество значащих цифр (называемых точностью) и будут ограничения на показатель степени (положительный и отрицательный). Между положительными и отрицательными числами может быть некоторая асимметрия, так что наименьшее отрицательное число может не совпадать по абсолютной величине с наибольшим положительным числом в системе (аналогично для диапазона показателей).

Для преувеличения эффекта арифметических операций с плавающей запятой я буду использовать довольно низкие ограничения. Я позволю до четырех значащих цифр (будет содержать -9от 0,999 до 9,999), я допущу степени от минус трех до четырех и буду использовать основание 10 для облегчения ручной проверки операций.

Давайте рассмотрим некоторые проблемы, связанные с арифметикой с плавающей запятой:

  1. Переполнение
  2. Недолив
  3. Потеря точности при преобразовании в число с плавающей запятой
  4. Сложение чисел очень разных величин
  5. Вычитание чисел с одинаковыми величинами
  6. Умножение и деление
  7. 9-4.

    Мы постоянно сталкиваемся с этой потерей точности в наших вычислениях, потому что наши числа преобразуются из десятичных в двоичные числа с плавающей запятой. Многие вещи, которые хорошо выглядят в десятичном виде, например 0,1 или 0,4, в двоичном виде повторяются. В двоичном формате 0,5 имеет прекрасное представление: 0,1. Поэтому, когда мы конвертируем 0,1 и 0,4 в двоичные числа, теряя при этом точность, а затем пытаемся вычесть их из 0,5, мы не получаем 0. накладывает потолок на количество сигфигов, которое вам разрешено иметь. Это дает вам представление о том, как теряется точность при операциях с плавающей запятой. 9-1? То есть мы пытаемся прибавить 777,7 к .9555.

    В точной арифметике ответ равен 778,6555. Но это слишком много значащих цифр для нашей системы с плавающей запятой. Мы должны округлить это число до 778,7, чтобы оно соответствовало нашей системе. Разница между округленным ответом и нашим точным ответом составляет 0,0445. В относительном выражении это незначительная ошибка, так что, возможно, это нас не беспокоит.

    Но что должно беспокоить нас, так это когда мы делаем что-то вроде сложения набора чисел, которые в конечном итоге должны давать одно, но каждое из которых очень мало. -3 к 9.-1. В нашей системе это получается так: 0,9999 + 0,00001 = 0,99991 = 0,9999. Теперь предположим, что мы пытаемся добавить этот столбец чисел:

    9-3 равносильно добавлению нуля к 0,9999.

    Как с этим справиться?

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

    В простом подходе вы добавили бы этот столбец чисел снизу вверх, и тогда они дадут в сумме 1. Обратите внимание, что сложение с плавающей запятой не является ассоциативным. Разве это не интересно?

    Другой подход заключается в добавлении каждого из этих наименьших чисел попарно, а затем добавлении этих пар друг к другу. 9-3.

    Совет 2. Перед вычитанием чисел с плавающей запятой может потребоваться «помассировать» исходные числа или изменить алгоритм, чтобы не потерять значащие цифры при вычитании.

    Проверьте ссылку Википедии в ресурсах, чтобы увидеть примеры потери значимости, особенно в квадратичной формуле, когда b велико, а 4ac очень мало.

    Умножение и деление
    Проблема с умножением и делением связана с переполнением и недостатком.

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

    Используя нашу систему, предположим, что вы хотите сделать:

    (99990 * 19990 * 22220) / ( 11110 * 77770)

    Если бы мы делали это строго слева направо, мы бы переполнились при нашей первой операции. Если бы мы вычислили это так:

    1/77770 * 1/11110 * (99990 * 199990 * 22220)

    , мы бы потеряли значение при первом умножении двух обратных величин.

    То, что вы хотели бы сделать, это изменить порядок шагов (есть несколько способов сделать это, чтобы предотвратить проблемы):

    (99990/77770) * (22220/11110) * 194 (в нашей системе)

    Совет 3: Чтобы избежать переполнения и потери значимости (а также потери точности) при умножении и делении чисел, попробуйте переставить произведение так, чтобы оно умножалось на числа, близкие к единице.

    Можно также попробовать превратить произведения в суммы с помощью логарифмов. Давайте представим, что наша функция журнала (база 10) работает аналогично нашей системе с плавающей запятой.

    Тогда получаем: log(99990) + log(19990) + log(22220) – log(11110) – log(77770) = 4,711 94

    Таким образом, мы получаем небольшую потерю точности в этом подходе, но сделать это преобразование может быть проще, чем пытаться перетасовать члены в вычислении. Я пробовал оба этих подхода в задаче биномиальной аппроксимации с переменным успехом.

    Совет 4. Иногда преобразование вычисления путем применения функции (например, логарифмирования) может устранить опасность переполнения и потери значимости, хотя это может стать новым источником потери точности.

    Источник: веб-сайт xkcd

    Во многих (если не в большинстве) актуарных расчетах мы не подошли близко к тем ситуациям, которые вызывают эти проблемы. Однако, поскольку нам приходится решать более сложные числовые задачи, а именно в этом направлении движутся многие системы регулирования и управления рисками, мы можем столкнуться с ними.

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

    Ресурсы и ссылки

    Предыдущие статьи автора по теме

    .9999
    .00001
    .00001
    .00001
    .00001
    .00001
    .00001
    .00001
    .00001
    .00001