Что такое 32 bit float

32 битых

Поздравляем, с некоторых пор наши любимые «24 бит» подросли на треть. Ожидать ли роста надоев и шерсти или это очередные маркетинговые тарахтелки? Рассмотрим 32 бита прямо в студии звукозаписи.

Коммерческих фонограмм, изданных «в 32-битовом исчислении», пока нет. Все хорошо расслышали? Не-ту.

Зато ЦАПов с 32-битовой разрядностью на всех углах — оптом, и в розницу, и на разлив. Например, ESS Sabre ES9018, Texas Instruments PCM1795 или Asahi Kasei AK4399. Все эти комплектующие успешно обкатаны в современных и уже не очень моделях для домашнего аудио. При этом, опять же, если мы заглянем на студию, то самые дорогие аналого-цифровые преобразователи по-прежнему будут иметь предел лишь до 24 бит/192 кГц. Но все-таки 32-битовое исчисление — полезная штука. Не знаем, как там в ЦАПе, а вот на этапе подготовки фонограммы частенько используется обработка данных с 32-битовой точностью. А иногда даже и 64. Как это работает? Начнем с финала.

Допустим, вы типичный издатель, чтоб, не дай бог, какой аудиофильский лейбл с занудным репертуаром. Обычная студия, которая готовит мастер к выпуску. Стандартный круг будущих носителей — CD, MP3 для веб-сервисов и винил. Как правило, для всех этих нужд хватает одного-единственного цифрового мастера в 24 бит/44 кГц. Де-факто на сегодня это финальный студийный продукт, которым оперируют в подавляющем большинстве случаев. Все, что выше, оговаривается по специальным заказам и встречается гораздо реже. Вам кажется 24/44 маловато? Да, частотка как у компакт-диска, но все-таки 24 бит дают более гладкое представление аудиоданных. По сравнению с CD такой файл звучит ну. не как небо и земля, но определенно плотнее, четче, с лучшей фокусировкой. Кстати, на ресурсах вроде HD Tracks или Qobuz вот именно такие 24/44 и предлагаются к продаже. Чтобы получить хороший результат на финальном мастере 24/44, инженерам звукозаписи имеет смысл позаботиться о некотором запасе.

А как же наши двухпудовые ЦАПы, зачем же все это надо?

«32 bit float» — т.е. 32 бит с плавающей точкой — вот как это называется в интерфейсе программных аудиоредакторов. АЦП может цифровать аналоговый сигнал максимально в 24 бит/192 кГц, но обычно звук записывают хоть и в 24 бит, но с более низкой частотой дискретизации, например 48 кГц. При этом каждому блоку данных аудиоредактор присваивает дополнительно 8 разрядов. По факту это не «настоящее», а виртуальное 32-битовое представление сигнала, они пока остаются пустыми. Зато потом на стадии микширования или редактирования эта «восьмерка пик» сможет пригодиться, пускай и не вся колода.

Например, вы сложили несколько дорожек. Или слишком бодро компрессировали амплитуду, чтобы разогнать громкость, и получили перехлест уровня выше 0 дБ. Для цифрового сигнала упереться в 0 дБ — это необратимый клиппинг, искажения, которые не отмотать назад. Так и было бы, если бы вы ворочали микс в родной 24-битовой среде. Вот здесь и приходят на помощь дополнительные 8 разрядов от звукового софта. Они дают необходимый «headroom», т.е. запас динамики, с помощью которого можно исправить ошибку — поправить уровень, более тщательно наложить эффект и т.п. Далее в самом конце все понижается в 24-битовый микс, а потом и в 16-битовый — для компакт-дисков и iTunes.

А как же наши двухпудовые ЦАПы, зачем же все это надо? «Опять обман?» — воскликнет читатель. «А что вам, собственно, — ответит редакция, — жалко, что ли?» За восемь лишних бит сверху денег не берут. А если когда и берут, то из-за колебаний валютного курса. Сладчайших вам прейскурантов и крепкой скидки в аудиосалонах!

Источник

Про Float в аудио популярно (1 онлайн

Entrase

Поделюсь тем, что знаю

Сразу прошу прощения за разговоры про «плавную волну». При всём своём новичковском звучании такие изъяснения легко визуализируются в мыслях. В дебри программирования и математики лазить не буду, рассказываю для всех.

Про Float в аудио популярно

Где нам только не попадается надпись вроде «32 bit float» — в спецификациях, обзорах, руководствах. К сожалению, последний элемент этой надписи часто недооценивается или вовсе игнорируется, и формат ставится в один ряд с привычными нам 16- или 24-битными. То есть многие просто не осведомлены о преимуществах представления с плавающей запятой («float» — плавающий). Потому распространены суждения в духе «зачем 32, если мне и 24 достаточно». Разберёмся, зачем и где это всё-таки нужно.

Когда речь идёт о 16, 20, 24 или 48 битах, то обычно под этим подразумевается противоположность плавающей запятой — фиксированная запятая. Подписывается это как «int», то есть integer — целочисленный, т.к. в этом виде удобно представлять целые числа. Именно о представлении с фиксированной запятой считает своим долгом рассказать любой автор, пишущий об основах цифрового звука. Поэтому не будем вдаваться подробности, а лишь вспомним, что 00 = 0, 01 = 1, 10 = 2, 11 = 3 и т.д., но только с соответствующим числом разрядов (разряды и биты — одно и то же в данном контексте, если что Правда, один бит отдаётся под знак — так удобнее представлять «цифровую волну», которая колеблется в обе стороны относительно нуля. С разным количеством бит получается разный диапазон чисел, но самое большое по модулю число в этом диапазоне всё равно соответствует 0 дБ. Это пресловутый Full Scale, выше которого не прыгнешь, т.к. все биты уже единицы. Но иногда прыгнуть нужно.

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

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

Как же float позволяет нам прыгнуть выше 0 дБ? По правде говоря, помогает не float, а тот факт, что 0 дБ в данном случае соответствует не максимальному числу с плавающей запятой, а намного меньшему. То же самое можно сделать и в целых числах. Взять, скажем, в 16-битном диапазоне за ноль не 32768, а раза в два меньше. Но разве для сильных перепадов нам достаточно такого запаса? Нет. Хорошо, float мы обычно видим в 32-битном исполнении. Возьмём тогда и для целого числа 32 бита. Поставим ноль посередине. Запас будет куда больше. Но для сильных многократных изменений этого всё равно может оказаться недостаточно. А если и хватит (работать и обрабатывать можно по-разному), то это лишняя головная боль программистам: необходимо отслеживать переполнения (когда все единицы и дальше некуда) и потери значимости (когда все нули). А наткнуться на эти эффекты при фиксированном формате куда проще, чем с плавающей запятой.

Почему? Потому что числа кодируются нулями и единицами иначе. Если в целочисленных форматах мы имели подход «в лоб» с переключением нулей на единички по порядку в одном большом поле (бит под знак сути не меняет), то здесь уже имеются два поля: мантисса и показатель степени. По стандарту IEEE754 число одинарной точности имеет 8-битный показатель и 23-битную мантиссу (1 бит под знак). Более глубоко тема раскрывается в энциклопедиях. Это называется экспоненциальной записью, и все её знают. В школе на физике и математике рассказывают, что число 1 536 000 можно записать как 1,536 × 10^6. 6 — показатель степени, 1,536 — мантисса. Не слишком напрягаясь можно манипулировать порядком числа — достаточно изменять показатель (1,536 × 10^−6). Довольно школьного материала, всё есть в учебниках и справочниках в достаточно сжатом виде. Вывод прост: волна будет оставаться плавной на самых разных уровнях, причём куда более разных, чем при обычной нотации. То есть звук не будет терять качество даже при очень серьёзных «регулировках громкости».

За 0 дБ в «плавающих форматах» берётся единица (1,00000…). Форматы эти имеют знак, как и целочисленные. Например, в 16 битах имеем числовой диапазон от −32768 до 32767. Вот эти пределы по децибелам и соответствуют промежутку −1,00—1,00 в плавающем виде. Но пределы самого плавающего вида куда шире диапазона от −1,00 до 1,00. Больше настолько, что уже в 32-битном представлении с плавающей запятой без ущерба для звука можно делать регулировки на сотни децибел! Вот так.

Почти панацея для программистов и серьёзное упрощение рабочего процесса для звукоинженеров. Почему почти? Потому что не всегда была и не всегда есть возможность применить соответствующие процессоры или снабдить процессор устройством для вычислений с плавающей запятой. Причём раньше проблема проявляла себя сильнее. Те стандарты и решения, которые становились давно по меркам вычислительной техники, завязаны на целых числах. По мере обновления техники вычисления с плавающей запятой задействуются шире. Например, новая звуковая подсистема ОС Windows Vista построена полностью на float-формате. Ещё программистам фирма Intel подарила ложку дёгтя в виде жутких тормозов своих процессоров при работе с очень мелкими числами. Впрочем, пользователей данная проблема не касается, т.к. программисты успешно обходят этот баг. На звук это не влияет, т.к. речь о действительно мелких числах. Не спешите погружаться в негодование и бежать за другими процессорами к другим фирмам. Особенность эта очень старая и присуща всем совместимым камням.

При всех положительных сторонах не везде целесообразно применять вычисления с плавающей запятой. На сегодняшний день не существует АЦП/ЦАП, способных полностью покрыть даже 24 бита, не говоря уже о чём-то большем. А значит, и нет смысла выбирать плавающие форматы для конечного продукта. Их предназначение — промежуточные результаты хоть в виде файлов, хоть внутри микшера виртуальной студии. Вне компьютера вычисления с плавающей запятой пока что распространения не получили. Конечно, они используются, например, в декодерах, а есть и вовсе отдельный класс процессоров — сигнальные. Но это закрытые для пользователя системы, и ему плевать, как там внутри его проигрывателя реализовано декодирование MP3. Студийные железки через AES3 передают звук целыми числами. А в бытовой технике поддержка огромного диапазона внешними интерфейсами совсем не нужна. Наверное, такой изолированностью и можно объяснить отсутствие 16-, 20-, 24- и прочих разрядностей, частых для фиксированных представлений.

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

Источник

Одинарная или двойная точность?

Введение

Статья также написана для тех из вас, у кого много данных. Если вам требуется несколько чисел тут или там, просто используйте 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

Выделенная жирным часть называется мантиссой, а выделенная курсивом — экспонентой. Вкратце, точность хранится в мантиссе, а величина в экспоненте. Так как с ними работать? Ну, умножение производится просто: перемножаем мантисссы и складываем экспоненты:

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

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

Источник

Что нужно знать про арифметику с плавающей запятой

Что такое 32 bit float. Смотреть фото Что такое 32 bit float. Смотреть картинку Что такое 32 bit float. Картинка про Что такое 32 bit float. Фото Что такое 32 bit float

В далекие времена, для IT-индустрии это 70-е годы прошлого века, ученые-математики (так раньше назывались программисты) сражались как Дон-Кихоты в неравном бою с компьютерами, которые тогда были размером с маленькие ветряные мельницы. Задачи ставились серьезные: поиск вражеских подлодок в океане по снимкам с орбиты, расчет баллистики ракет дальнего действия, и прочее. Для их решения компьютер должен оперировать действительными числами, которых, как известно, континуум, тогда как память конечна. Поэтому приходится отображать этот континуум на конечное множество нулей и единиц. В поисках компромисса между скоростью, размером и точностью представления ученые предложили числа с плавающей запятой (или плавающей точкой, если по-буржуйски).

Арифметика с плавающей запятой почему-то считается экзотической областью компьютерных наук, учитывая, что соответствующие типы данных присутствуют в каждом языке программирования. Я сам, если честно, никогда не придавал особого значения компьютерной арифметике, пока решая одну и ту же задачу на CPU и GPU получил разный результат. Оказалось, что в потайных углах этой области скрываются очень любопытные и странные явления: некоммутативность и неассоциативность арифметических операций, ноль со знаком, разность неравных чисел дает ноль, и прочее. Корни этого айсберга уходят глубоко в математику, а я под катом постараюсь обрисовать лишь то, что лежит на поверхности.

1. Основы

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

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

Что такое 32 bit float. Смотреть фото Что такое 32 bit float. Смотреть картинку Что такое 32 bit float. Картинка про Что такое 32 bit float. Фото Что такое 32 bit float

Математически это записывается так:

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

Что такое мантисса и порядок? Мантисса – это целое число фиксированной длины, которое представляет старшие разряды действительного числа. Допустим наша мантисса состоит из трех бит (|M|=3). Возьмем, например, число «5», которое в двоичной системе будет равно 1012. Старший бит соответствует 2 2 =4, средний (который у нас равен нулю) 2 1 =2, а младший 2 0 =1. Порядок – это степень базы (двойки) старшего разряда. В нашем случае E=2. Такие числа удобно записывать в так называемом «научном» стандартном виде, например «1.01e+2». Сразу видно, что мантисса состоит из трех знаков, а порядок равен двум.

Допустим мы хотим получить дробное число, используя те же 3 бита мантиссы. Мы можем это сделать, если возьмем, скажем, E=1. Тогда наше число будет равно

2 = 10 (в двоичной системе) = 1.000e+1 = 0.100e+2 = 0.010e+3. (E=1, E=2, E=3 соответственно)

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

Что такое 32 bit float. Смотреть фото Что такое 32 bit float. Смотреть картинку Что такое 32 bit float. Картинка про Что такое 32 bit float. Фото Что такое 32 bit float

Это экономит один бит, так как неявную единицу не нужно хранить в памяти, и обеспечивает уникальность представления числа. В нашем примере «2» имеет единственное нормализованное представление («1.000e+1»), а мантисса хранится в памяти как «000», т.к. старшая единица подразумевается неявно. Но в нормализованном представлении чисел возникает новая проблема — в такой форме невозможно представить ноль.

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

Качество решения задач во многом зависит от выбора представления чисел с плавающей запятой. Мы плавно подошли к проблеме стандартизации такого представления.

2. Немного истории

В 60-е и 70-е годы не было единого стандарта представления чисел с плавающей запятой, способов округления, арифметических операций. В результате программы были крайне не портабельны. Но еще большей проблемой было то, что у разных компьютеров были свои «странности» и их нужно было знать и учитывать в программе. Например, разница двух не равных чисел возвращала ноль. В результате выражения «X=Y» и «X-Y=0» вступали в противоречие. Умельцы обходили эту проблему очень хитрыми трюками, например, делали присваивание «X=(X-X)+X» перед операциями умножения и деления, чтобы избежать проблем.

Инициатива создать единый стандарт для представления чисел с плавающей запятой подозрительно совпала с попытками в 1976 году компанией Intel разработать «лучшую» арифметику для новых сопроцессоров к 8086 и i432. За разработку взялись ученые киты в этой области, проф. Джон Палмер и Уильям Кэхэн. Последний в своем интервью высказал мнение, что серьезность, с которой Intel разрабатывала свою арифметику, заставила другие компании объединиться и начать процесс стандартизации.

Все были настроены серьезно, ведь очень выгодно продвинуть свою архитектуру и сделать ее стандартной. Свои предложения представили компании DEC, National Superconductor, Zilog, Motorola. Производители мейнфреймов Cray и IBM наблюдали со стороны. Компания Intel, разумеется, тоже представила свою новую арифметику. Авторами предложенной спецификации стали Уильям Кэхэн, Джероми Кунен и Гарольд Стоун и их предложение сразу прозвали «K-C-S».

Практически сразу же были отброшены все предложения, кроме двух: VAX от DEC и «K-C-S» от Intel. Спецификация VAX была значительно проще, уже была реализована в компьютерах PDP-11, и было понятно, как на ней получить максимальную производительность. С другой стороны в «K-C-S» содержалось много полезной функциональности, такой как «специальные» и «денормализованные» числа (подробности ниже).

В «K-C-S» все арифметические алгоритмы заданы строго и требуется, чтобы в реализации результат с ними совпадал. Это позволяет выводить строгие выкладки в рамках этой спецификации. Если раньше математик решал задачу численными методами и доказывал свойства решения, не было никакой гарантии, что эти свойства сохранятся в программе. Строгость арифметики «K-C-S» сделала возможным доказательство теорем, опираясь на арифметику с плавающей запятой.

Компания DEC сделала все, чтобы ее спецификацию сделали стандартом. Она даже заручилась поддержкой некоторых авторитетных ученых в том, что арифметика «K-C-S» в принципе не может достигнуть такой же производительности, как у DEC. Ирония в том, что Intel знала, как сделать свою спецификацию такой же производительной, но эти хитрости были коммерческой тайной. Если бы Intel не уступила и не открыла часть секретов, она бы не смогла сдержать натиск DEC.

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

3. Представление чисел с плавающей запятой сегодня

Разработчики «K-C-S» победили и теперь их детище воплотилось в стандарт IEEE754. Числа с плавающей запятой в нем представлены в виде знака (s), мантиссы (M) и порядка (E) следующим образом:

Замечание. В новом стандарте IEE754-2008 кроме чисел с основанием 2 присутствуют числа с основанием 10, так называемые десятичные (decimal) числа с плавающей запятой.

Чтобы не загромождать читателя чрезмерной информацией, которую можно найти в Википедии, рассмотрим только один тип данных, с одинарной точностью (float). Числа с половинной, двойной и расширенной точностью обладают теми же особенностями, но имеют другой диапазон порядка и мантиссы. В числах одинарной точности (float/single) порядок состоит из 8 бит, а мантисса – из 23. Эффективный порядок определяется как E-127. Например, число 0,15625 будет записано в памяти как

Что такое 32 bit float. Смотреть фото Что такое 32 bit float. Смотреть картинку Что такое 32 bit float. Картинка про Что такое 32 bit float. Фото Что такое 32 bit float
Рисунок взят из Википедии

3.1 Специальные числа: ноль, бесконечность и неопределенность

Неопределенность или NaN (от not a number) – это представление, придуманное для того, чтобы арифметическая операция могла всегда вернуть какое-то не бессмысленное значение. В IEEE754 NaN представлен как число, в котором E=Emax+1, а мантисса не нулевая. Любая операция с NaN возвращает NaN. При желании в мантиссу можно записывать информацию, которую программа сможет интерпретировать. Стандартом это не оговорено и мантисса чаще всего игнорируется.

Вернемся к примеру. Наш Emin=-1. Введем новое значение порядка, E=-2, при котором числа являются денормализованными. В результате получаем новое представление чисел:

Что такое 32 bit float. Смотреть фото Что такое 32 bit float. Смотреть картинку Что такое 32 bit float. Картинка про Что такое 32 bit float. Фото Что такое 32 bit float

Интервал от 0 до 0,5 заполняют денормализованные числа, что дает возможность не проваливаться в 0 рассмотренных выше примерах (0,5-0,25 и 1,5-1,25). Это сделало представление более устойчиво к ошибкам округления для чисел, близких к нулю.

Но роскошь использования денормализованного представления чисел в процессоре не дается бесплатно. Из-за того, что такие числа нужно обрабатывать по-другому во всех арифметических операциях, трудно сделать работу в такой арифметике эффективной. Это накладывает дополнительные сложности при реализации АЛУ в процессоре. И хоть денормализованные числа очень полезны, они не являются панацеей и за округлением до нуля все равно нужно следить. Поэтому эта функциональность стала камнем преткновения при разработке стандарта и встретила самое сильное сопротивление.

3.4 Очередность чисел в IEEE754

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

4.2 Неассоциативность арифметических операций

В арифметике с плавающей запятой правило (a*b)*c = a*(b*c) не выполняется для любых арифметических операций. Например,

Допустим у нас есть программа суммирования чисел.

Некоторые компиляторы по умолчанию могут переписать код для использования нескольких АЛУ одновременно (будем считать, что n делится на 2):

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

4.3 Числовые константы

Помните, что не все десятичные числа имеют двоичное представление с плавающей запятой. Например, число «0,2» будет представлено как «0,200000003» в одинарной точности. Соответственно, «0,2 + 0,2 ≈ 0,4». Абсолютная погрешность в отдельном
случае может и не высока, но если использовать такую константу в цикле, можем получить накопленную погрешность.

4.4 Выбор минимума из двух значений
4.5 Сравнение чисел

Очень распространенная ошибка при работе с float-ами возникает при проверке на равенство. Например,

Ошибка здесь, во-первых, в том, что 0,2 не имеет точного двоичного представления, а во-вторых 0,2 – это константа двойной точности, а переменная fValue – одинарной, и никакой гарантии о поведении этого сравнения нет.

Лучший, но все равно ошибочный способ, это сравнивать разницу с допустимой абсолютной погрешностью:

Недостаток такого подхода в том, что погрешность представления числа увеличивается с ростом самого этого числа. Так, если программа ожидает «10000», то приведенное равенство не будет выполняться для ближайшего соседнего числа (10000,000977). Это особенно актуально, если в программе имеется преобразование из одинарной точности в двойную.

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

5. Проверка полноты поддержки IEE754

Думаете, что если процессоры полностью соответствуют стандарту IEEE754, то любая программа, использующая стандартные типы данных (такие как float/double в Си), будет выдавать один и тот же результат на разных компьютерах? Ошибаетесь. На портабельность и соответствие стандарту влияет компилятор и опции оптимизации. Уильям Кэхэн написал программу на Си (есть версия и для Фортрана), которая позволяет проверить удовлетворяет ли связка «архитектура+компилятор+опции» IEEE754. Называется она «Floating point paranoia» и ее исходные тексты доступны для скачивания. Аналогичная программа доступна для GPU. Так, например, компилятор Intel (icc) по умолчанию использует «расслабленную» модель IEEE754, и в результате не все тесты выполняются. Опция «-fp-model precise» позволяет компилировать программу с точным соответствием стандарту. В компиляторе GCC есть опция «-ffast-math», использование которой приводит к несоответствию IEEE754.

Заключение

Напоследок поучительная история. Когда я работал над тестовым проектом на GPU, у меня была последовательная и параллельная версия одной программы. Сравнив время выполнения, я был очень обрадован, так как получил ускорение в 300 раз. Но позже оказалось, что вычисления на GPU «разваливались» и обращались в NaN, а работа с ними в GPU была быстрее, чем с обычными числами. Интересно было другое — одна и та же программа на эмуляторе GPU (на CPU) выдавала корректный результат, а на самом GPU – нет. Позже оказалось, что проблема была в том, что этот GPU не поддерживал полностью стандарт IEEE754 и прямой подход не сработал.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *