В вычислительной технике арифметика с плавающей точкой ( FP ) в некоторой базе (или системе счисления счисления ) — это арифметика , которая представляет подмножества действительных чисел с использованием значения с фиксированной точкой (называемого мантиссом ) в этой базе с фиксированной точностью, масштабируемой целой степенью (определяемой показателем) этой базы. Числа этой формы называются числами с плавающей точкой . [1] : 3 [2] : 10
Например, 12,345 можно записать в формате с плавающей точкой в десятичной системе счисления с точностью до пяти цифр: выбрав запись значащей части с десятичной точкой после пятой цифры. Однако, в отличие от 12,345, 12,3456 нельзя записать в пятизначном формате с плавающей точкой в десятичной системе счисления, для этого требуется точность до шести цифр. Ближайшее число с плавающей точкой, содержащее всего пять цифр, — это 12,346. На практике большинство систем с плавающей точкой используют основание два , хотя основание десять ( десятичное с плавающей точкой ) также распространено.
Арифметические операции с плавающей точкой, такие как сложение и деление, приближают соответствующие арифметические операции с действительными числами, округляя любой результат, который сам по себе не является числом с плавающей точкой, до ближайшего числа с плавающей точкой. [1] : 22 [2] : 10 Например, в арифметике с плавающей точкой с точностью пять десятичных знаков сумма 12,345 + 1,0001 = 13,3451 может быть округлена до 13,345.
Термин «плавающая точка» относится к тому факту, что точка основания числа может «плавать» где угодно слева, справа или между значимыми цифрами числа. Эта позиция указывается экспонентой, поэтому плавающую точку можно считать формой научной записи .
Система с плавающей точкой может использоваться для представления с фиксированным числом цифр чисел самых разных порядков величины — например, числа метров между галактиками или между протонами в атоме . По этой причине арифметика с плавающей точкой часто используется для разрешения очень маленьких и очень больших действительных чисел, требующих быстрого времени обработки. Результатом этого динамического диапазона является то, что числа, которые могут быть представлены, неравномерно распределены; разница между двумя последовательными представимыми числами меняется в зависимости от их показателя степени. [3]
На протяжении многих лет в компьютерах использовались различные представления с плавающей точкой. В 1985 году был установлен стандарт IEEE 754 для арифметики с плавающей точкой, а с 1990-х годов наиболее часто встречающимися представлениями являются те, которые определены IEEE.
Скорость операций с плавающей точкой, обычно измеряемая в единицах FLOPS , является важной характеристикой компьютерной системы , особенно для приложений, требующих интенсивных математических вычислений.
Устройство с плавающей точкой (FPU, в просторечии математический сопроцессор ) — это часть компьютерной системы, специально разработанная для выполнения операций с числами с плавающей точкой.
Представление числа определяет некоторый способ кодирования числа, обычно в виде строки цифр.
Существует несколько механизмов, с помощью которых строки цифр могут представлять числа. В стандартной математической нотации строка цифр может быть любой длины, а местоположение точки основания указывается путем размещения там явного символа «точки» (точки или запятой). Если точка основания не указана, то строка неявно представляет целое число , а неуказанная точка основания будет находиться за правым концом строки, рядом с наименее значащей цифрой. В системах с фиксированной точкой позиция в строке указывается для точки основания. Таким образом, схема с фиксированной точкой может использовать строку из 8 десятичных цифр с десятичной точкой посередине, в результате чего «00012345» будет представлять 0001.2345.
В научной нотации заданное число масштабируется степенью 10 , так что оно находится в определенном диапазоне — обычно между 1 и 10, с точкой основания, появляющейся сразу после первой цифры. Как степень десяти, коэффициент масштабирования затем указывается отдельно в конце числа. Например, орбитальный период спутника Юпитера Ио равен152 853,5047 секунд, значение, которое в стандартной форме научной записи будет представлено как1,528535047 × 10 5 секунд.
Представление с плавающей точкой по своей концепции похоже на научную запись. Логически число с плавающей точкой состоит из:
Чтобы получить значение числа с плавающей точкой, мантисса умножается на основание, возведенное в степень показателя степени , что эквивалентно сдвигу запятой из ее подразумеваемого положения на количество знаков, равное значению показателя степени — вправо, если показатель степени положительный, или влево, если показатель степени отрицательный.
Используя в качестве примера основание 10 (знакомую десятичную систему счисления), числоЧисло 152,853.5047 , имеющее десять десятичных знаков точности, представлено как значащая часть1 528 535 047 вместе с 5 в качестве показателя степени. Для определения фактического значения десятичная точка ставится после первой цифры значащей части, а результат умножается на 105 дать1,528535047 × 10 5 , или152 853,5047 . При сохранении такого числа основание (10) хранить не нужно, поскольку оно будет одинаковым для всего диапазона поддерживаемых чисел и, таким образом, может быть выведено.
Символически это конечное значение равно:
где s — мантисса (игнорируя любую подразумеваемую десятичную точку), p — точность (количество цифр в мантиссе), b — основание (в нашем примере это число десять ), а e — показатель степени.
Исторически для представления чисел с плавающей точкой использовалось несколько систем счисления, при этом наиболее распространенной является система счисления с основанием два ( двоичная ), за которой следует система счисления с основанием десять ( десятичная с плавающей точкой ), а также другие менее распространенные разновидности, такие как система счисления с основанием шестнадцать ( шестнадцатеричная с плавающей точкой [4] [5] [nb 3] ), система с основанием восемь (восьмеричная с плавающей точкой [1] [5] [6] [4] [nb 4] ), система с основанием четыре (четвертичная с плавающей точкой [7] [5] [nb 5] ), система с основанием три ( сбалансированная троичная с плавающей точкой [1] ) и даже система с основанием 256 [5] [nb 6] и система с основанием65 536 . [8] [прим. 7]
Число с плавающей точкой является рациональным числом , поскольку его можно представить как одно целое число, деленное на другое; например1,45 × 10 3 равно (145/100)×1000 или145 000 / 100. Основание определяет дроби, которые могут быть представлены; например, 1/5 не может быть точно представлено как число с плавающей точкой с использованием двоичного основания, но 1/5 может быть точно представлено с использованием десятичного основания (0,2 или2 × 10 −1 ). Однако 1/3 не может быть точно представлена ни двоичной (0,010101...), ни десятичной (0,333...), но в системе счисления с основанием 3 она тривиальна (0,1 или 1×3 −1 ) . Случаи, когда происходят бесконечные расширения, зависят от основания и его простых множителей .
Способ, которым мантисса (включая ее знак) и показатель степени хранятся в компьютере, зависит от реализации. Общие форматы IEEE подробно описаны позже и в другом месте, но в качестве примера, в двоичном представлении с плавающей точкой одинарной точности (32 бита), и поэтому мантисса представляет собой строку из 24 бит . Например, первые 33 бита числа π следующие:
В этом двоичном расширении обозначим позиции от 0 (самый левый бит или самый значимый бит) до 32 (самый правый бит). 24-битная мантисса остановится на позиции 23, показанной как подчеркнутый бит0 выше. Следующий бит, в позиции 24, называется битом округления или битом округления . Он используется для округления 33-битного приближения до ближайшего 24-битного числа (существуют особые правила для половинных значений , что в данном случае не так). Этот бит, которыйВ этом примере 1 добавляется к целому числу, образованному крайними левыми 24 битами, что дает:
Когда это сохраняется в памяти с использованием кодировки IEEE 754, это становится мантиссом s . Предполагается, что мантисса имеет двоичную точку справа от самого левого бита. Таким образом, двоичное представление π вычисляется слева направо следующим образом:
где p — точность (24 в этом примере), n — это позиция бита мантиссы слева (начиная с0 и заканчивая на23 здесь) и e - показатель степени (1 в этом примере).
Можно потребовать, чтобы старший разряд мантиссы ненулевого числа был ненулевым (за исключением случаев, когда соответствующая экспонента будет меньше минимальной). Этот процесс называется нормализацией . Для двоичных форматов (которые используют только цифры0 и1 ), эта ненулевая цифра обязательно1 . Поэтому его не нужно представлять в памяти, что позволяет формату иметь еще один бит точности. Это правило по-разному называется соглашением о ведущих битах , неявным соглашением о битах , скрытым соглашением о битах [1] или предполагаемым соглашением о битах .
Представление с плавающей точкой является наиболее распространенным способом представления в компьютерах приближения к действительным числам. Однако существуют и альтернативы:
В 1914 году испанский инженер Леонардо Торрес Кеведо опубликовал «Очерки автоматики» [ 9] , где он спроектировал специализированный электромеханический калькулятор на основе аналитической машины Чарльза Бэббиджа и описал способ хранения чисел с плавающей точкой согласованным образом. Он заявил, что числа будут храниться в экспоненциальном формате как n x 10 , и предложил три правила, с помощью которых можно реализовать согласованную обработку чисел с плавающей точкой машинами. Для Торреса « n всегда будет иметь одинаковое количество цифр (например, шесть), первая цифра n будет иметь порядок десятых, вторая — сотых и т. д., и каждую величину следует записывать в виде: n ; m ». Предложенный им формат показывает необходимость фиксированного размера мантиссы, который в настоящее время используется для данных с плавающей точкой, фиксируя местоположение десятичной точки в мантиссе так, чтобы каждое представление было уникальным, и как форматировать такие числа, указывая используемый синтаксис, который можно было бы ввести с помощью пишущей машинки , как это было в случае его электромеханического арифмометра в 1920 году. [10] [11] [12]
В 1938 году Конрад Цузе из Берлина завершил Z1 , первый двоичный программируемый механический компьютер ; [13] он использует 24-битное двоичное представление чисел с плавающей точкой с 7-битной знаковой экспонентой, 17-битной мантиссом (включая один неявный бит) и знаковым битом. [ 14] Более надежный релейный Z3 , завершенный в 1941 году, имеет представления как для положительных, так и для отрицательных бесконечностей; в частности, он реализует определенные операции с бесконечностью, такие как , и останавливается на неопределенных операциях, таких как .
Цузе также предложил, но не завершил, тщательно округленную арифметику с плавающей точкой, которая включает и представления NaN, предвосхищая возможности стандарта IEEE на четыре десятилетия. [15] Напротив, фон Нейман рекомендовал не использовать числа с плавающей точкой для машины IAS 1951 года , утверждая, что арифметика с фиксированной точкой предпочтительнее. [15]
Первым коммерческим компьютером с аппаратным обеспечением для работы с плавающей точкой был компьютер Z4 Цузе , разработанный в 1942–1945 годах. В 1946 году Bell Laboratories представила Model V , в которой были реализованы десятичные числа с плавающей точкой . [16]
Pilot ACE имеет двоичную арифметику с плавающей точкой, и она начала работать в 1950 году в Национальной физической лаборатории Великобритании . Тридцать три были позже проданы на коммерческой основе как English Electric DEUCE . Арифметика фактически реализована в программном обеспечении, но с тактовой частотой в один мегагерц скорость операций с плавающей точкой и фиксированной точкой в этой машине изначально была выше, чем у многих конкурирующих компьютеров.
В 1954 году последовал массовый IBM 704 ; он ввел использование смещенной экспоненты . В течение многих десятилетий после этого аппаратное обеспечение с плавающей точкой обычно было дополнительной функцией, и компьютеры, которые имели ее, назывались «научными компьютерами» или имели возможность « научных вычислений » (SC) (см. также Расширения для научных вычислений (XSC)). Только с выпуском Intel i486 в 1989 году персональные компьютеры общего назначения имели аппаратную возможность с плавающей точкой в качестве стандартной функции.
Серия UNIVAC 1100/2200 , представленная в 1962 году, поддерживала два представления чисел с плавающей точкой:
IBM 7094 , также представленный в 1962 году, поддерживал представления с одинарной и двойной точностью, но не имел никакого отношения к представлениям UNIVAC. Действительно, в 1964 году IBM представила шестнадцатеричные представления с плавающей точкой в своих мэйнфреймах System/360 ; эти же представления по-прежнему доступны для использования в современных системах z/Architecture . В 1998 году IBM реализовала совместимую с IEEE двоичную арифметику с плавающей точкой в своих мэйнфреймах; в 2005 году IBM также добавила совместимую с IEEE десятичную арифметику с плавающей точкой.
Первоначально компьютеры использовали много различных представлений для чисел с плавающей точкой. Отсутствие стандартизации на уровне мэйнфреймов было постоянной проблемой к началу 1970-х годов для тех, кто писал и поддерживал исходный код более высокого уровня; эти стандарты производителей для чисел с плавающей точкой различались по размерам слов, представлениям, поведению округления и общей точности операций. Совместимость с плавающей точкой между несколькими вычислительными системами отчаянно нуждалась в стандартизации к началу 1980-х годов, что привело к созданию стандарта IEEE 754, как только 32-битное (или 64-битное) слово стало обычным явлением. Этот стандарт был в значительной степени основан на предложении Intel, которая проектировала числовой сопроцессор i8087 ; Motorola, которая проектировала 68000 примерно в то же время, также внесла значительный вклад.
В 1989 году математик и ученый-компьютерщик Уильям Кахан был удостоен премии Тьюринга за то, что он был главным архитектором этого предложения; ему помогали его студент Джером Кунен и приглашенный профессор Гарольд Стоун . [17]
Среди нововведений x86 можно выделить следующие:
Число с плавающей точкой состоит из двух компонентов с фиксированной точкой , диапазон которых зависит исключительно от количества бит или цифр в их представлении. В то время как компоненты линейно зависят от своего диапазона, диапазон с плавающей точкой линейно зависит от диапазона мантиссы и экспоненциально от диапазона компонента экспоненты, что придает числу значительно более широкий диапазон.
В типичной компьютерной системе двоичное число с плавающей точкой двойной точности (64 бита) имеет коэффициент 53 бита (включая 1 подразумеваемый бит), показатель степени 11 бит и 1 знаковый бит. Поскольку 2 10 = 1024, полный диапазон положительных нормальных чисел с плавающей точкой в этом формате составляет от 2 −1022 ≈ 2 × 10 −308 до приблизительно 2 1024 ≈ 2 × 10 308 .
Число обычных чисел с плавающей точкой в системе ( B , P , L , U ), где
является .
Существует наименьшее положительное нормальное число с плавающей точкой,
где ведущая цифра — 1, остальные цифры — 0, а показатель степени — наименьшее возможное значение.
Существует самое большое число с плавающей точкой,
где B − 1 является значением для каждой цифры мантиссы и максимально возможным значением для показателя степени.
Кроме того, существуют представимые значения строго между −UFL и UFL. А именно, положительные и отрицательные нули , а также субнормальные числа .
IEEE стандартизировал компьютерное представление двоичных чисел с плавающей точкой в IEEE 754 (он же IEC 60559) в 1985 году . Этому первому стандарту следуют почти все современные машины. Он был пересмотрен в 2008 году . Мейнфреймы IBM поддерживают собственный шестнадцатеричный формат с плавающей точкой IBM и десятичный формат с плавающей точкой IEEE 754-2008 в дополнение к двоичному формату IEEE 754. Серия Cray T90 имела версию IEEE, но SV1 по-прежнему использует формат с плавающей точкой Cray. [ необходима цитата ]
Стандарт предусматривает множество тесно связанных форматов, отличающихся лишь несколькими деталями. Пять из этих форматов называются базовыми форматами , а другие называются форматами расширенной точности и форматом расширяемой точности . Три формата особенно широко используются в компьютерном оборудовании и языках: [ необходима цитата ]
Увеличение точности представления с плавающей точкой обычно уменьшает количество накопленных ошибок округления, вызванных промежуточными вычислениями. [24] Другие форматы IEEE включают:
Любое целое число с абсолютным значением меньше 2 24 может быть точно представлено в формате одинарной точности, а любое целое число с абсолютным значением меньше 2 53 может быть точно представлено в формате двойной точности. Кроме того, может быть представлен широкий диапазон степеней 2, умноженных на такое число. Эти свойства иногда используются для чисто целочисленных данных, чтобы получить 53-битные целые числа на платформах, которые имеют числа с плавающей точкой двойной точности, но только 32-битные целые числа.
Стандарт определяет некоторые специальные значения и их представление: положительная бесконечность ( +∞ ), отрицательная бесконечность ( −∞ ), отрицательный ноль (−0), отличный от обычного («положительного») нуля, и значения «не число» ( NaN ).
Сравнение чисел с плавающей точкой, как определено стандартом IEEE, немного отличается от обычного сравнения целых чисел. Отрицательные и положительные нули сравниваются как равные, а каждое NaN сравнивается как неравное любому значению, включая себя. Все конечные числа с плавающей точкой строго меньше +∞ и строго больше −∞ , и они упорядочены так же, как и их значения (в наборе действительных чисел).
Числа с плавающей точкой обычно упаковываются в компьютерные данные как бит знака, поле экспоненты и мантиссу или мантиссу, слева направо. Для двоичных форматов IEEE 754 (базового и расширенного), которые имеют существующие аппаратные реализации, они распределяются следующим образом:
Хотя показатель степени может быть положительным или отрицательным, в двоичных форматах он хранится как беззнаковое число, к которому добавлено фиксированное «смещение». Значения всех нулей в этом поле зарезервированы для нулей и субнормальных чисел ; значения всех единиц зарезервированы для бесконечностей и NaN. Диапазон показателя степени для нормальных чисел составляет [−126, 127] для одинарной точности, [−1022, 1023] для двойной или [−16382, 16383] для четверной. Нормальные числа не включают субнормальные значения, нули, бесконечности и NaN.
В форматах двоичного обмена IEEE первый бит нормализованной мантиссы фактически не хранится в компьютерных данных. Он называется «скрытым» или «неявным» битом. Из-за этого формат одинарной точности на самом деле имеет мантису с точностью 24 бита, формат двойной точности — 53, а четверной — 113.
Например, выше было показано, что число π, округленное до точности 24 бит, имеет:
Сумма смещения показателя степени (127) и показателя степени (1) равна 128, поэтому в формате одинарной точности это представлено как
Пример макета для 32-битных чисел с плавающей точкой :
и 64-битная («двойная») раскладка аналогична.
Помимо широко используемых стандартных форматов IEEE 754 , в некоторых предметно-ориентированных областях используются или использовались и другие форматы с плавающей точкой.
По своей природе все числа, выраженные в формате с плавающей точкой, являются рациональными числами с конечным расширением в соответствующем основании (например, конечное десятичное расширение в основании 10 или конечное двоичное расширение в основании 2). Иррациональные числа, такие как π или √2, или неконечные рациональные числа, должны быть приближены. Количество цифр (или бит) точности также ограничивает набор рациональных чисел, которые могут быть представлены точно. Например, десятичное число 123456789 не может быть точно представлено, если доступны только восемь десятичных знаков точности (оно будет округлено до одного из двух представимых значений, 12345678 × 10 1 или 12345679 × 10 1 ), то же самое относится к неконечным цифрам (. 5 округляется до . 5555555 или . 55555556).
Когда число представлено в некотором формате (например, в виде строки символов), который не является собственным представлением с плавающей точкой, поддерживаемым в компьютерной реализации, то потребуется преобразование, прежде чем его можно будет использовать в этой реализации. Если число может быть представлено точно в формате с плавающей точкой, то преобразование будет точным. Если точного представления нет, то преобразование требует выбора, какое число с плавающей точкой использовать для представления исходного значения. Выбранное представление будет иметь значение, отличное от исходного, и скорректированное таким образом значение называется округленным значением .
Имеет ли рациональное число конечное расширение или нет, зависит от основания. Например, в десятичной системе счисления число 1/2 имеет конечное расширение (0,5), а число 1/3 — нет (0,333...). В двоичной системе счисления конечными являются только рациональные числа со знаменателями, являющимися степенями 2 (например, 1/2 или 3/16). Любое рациональное число со знаменателем, имеющим простой множитель, отличный от 2, будет иметь бесконечное двоичное расширение. Это означает, что числа, которые кажутся короткими и точными при записи в десятичном формате, могут нуждаться в аппроксимации при преобразовании в двоичный формат с плавающей точкой. Например, десятичное число 0,1 не может быть представлено в двоичном формате с плавающей точкой любой конечной точности; точное двоичное представление будет иметь последовательность «1100», продолжающуюся бесконечно:
где, как и ранее, s — мантисса, а e — показатель степени.
При округлении до 24 бит это становится
что на самом деле составляет 0,100000001490116119384765625 в десятичной системе счисления.
В качестве еще одного примера, действительное число π , представленное в двоичной системе счисления как бесконечная последовательность битов, равно
но есть
при округлении до точности 24 бита.
В двоичном представлении с плавающей точкой одинарной точности это представляется как s = 1,10010010000111111011011 с e = 1. Это имеет десятичное значение
тогда как более точное приближение истинного значения π равно
Результат округления отличается от истинного значения примерно на 0,03 миллионных частей и соответствует десятеричному представлению числа π в первых 7 цифрах. Разница является ошибкой дискретизации и ограничена машинным эпсилоном .
Арифметическая разность между двумя последовательными представимыми числами с плавающей точкой, имеющими одинаковую экспоненту, называется единицей на последнем месте (ULP). Например, если нет представимого числа, лежащего между представимыми числами 1.45a70c22 hex и 1.45a70c24 hex , то ULP равно 2×16 −8 или 2 −31 . Для чисел с основанием 2 экспоненциальной части 0, т. е. чисел с абсолютным значением больше или равным 1, но меньше 2, ULP равно ровно 2 −23 или около 10 −7 в одинарной точности и ровно 2 −53 или около 10 −16 в двойной точности. Предписанное поведение IEEE-совместимого оборудования заключается в том, что результат должен быть в пределах половины ULP.
Округление используется, когда для точного результата операции с плавающей точкой (или преобразования в формат с плавающей точкой) потребуется больше цифр, чем цифр в значащей части. IEEE 754 требует правильного округления : то есть округленный результат такой, как если бы для вычисления значения использовалась бесконечно точная арифметика, а затем округлялась (хотя в реализации для обеспечения этого требуется всего три дополнительных бита). Существует несколько различных схем округления (или режимов округления ). Исторически усечение было типичным подходом. С момента введения IEEE 754 чаще используется метод по умолчанию ( округление к ближайшему, привязка к четному , иногда называемый округлением банкира). Этот метод округляет идеальный (бесконечно точный) результат арифметической операции до ближайшего представимого значения и выдает это представление в качестве результата. [nb 8] В случае равенства выбирается значение, при котором значащая часть заканчивается четной цифрой. Стандарт IEEE 754 требует, чтобы одинаковое округление применялось ко всем фундаментальным алгебраическим операциям, включая квадратный корень и преобразования, когда есть числовой (не NaN) результат. Это означает, что результаты операций IEEE 754 полностью определены во всех битах результата, за исключением представления NaN. (Библиотечные" функции, такие как косинус и логарифм, не являются обязательными.)
Также доступны альтернативные варианты округления. IEEE 754 определяет следующие режимы округления:
Альтернативные режимы полезны, когда количество вносимой ошибки должно быть ограничено. Приложения, которым требуется ограниченная ошибка, — это многоточечная плавающая точка и интервальная арифметика . Альтернативные режимы округления также полезны при диагностике численной нестабильности: если результаты подпрограммы существенно различаются между округлением до + и − бесконечности, то она, скорее всего, численно нестабильна и подвержена ошибкам округления. [34]
Преобразование двоичного числа с плавающей точкой двойной точности в десятичную строку является обычной операцией, но алгоритм, дающий результаты, которые являются как точными, так и минимальными, не появлялся в печати до 1990 года, когда Steele and White's Dragon4. Некоторые из усовершенствований с тех пор включают:
Многие современные среды выполнения языка используют Grisu3 с резервным вариантом Dragon4. [41]
Проблема разбора десятичной строки в двоичное представление FP является сложной, и точный анализатор не появлялся до работы Клингера 1990 года (реализованной в dtoa.c). [35] Дальнейшая работа также продвигалась в направлении более быстрого разбора. [42]
Для простоты представления и понимания в примерах будет использоваться десятичная система счисления с точностью 7 цифр, как в формате IEEE 754 decimal32 . Основные принципы одинаковы для любой системы счисления или точности, за исключением того, что нормализация необязательна (она не влияет на численное значение результата). Здесь s обозначает мантиссу, а e обозначает показатель степени.
Простой метод сложения чисел с плавающей точкой — сначала представить их с той же экспонентой. В примере ниже второе число (с меньшей экспонентой) сдвигается вправо на три цифры, а затем выполняется обычный метод сложения:
123456,7 = 1,234567 × 10^5 101,7654 = 1,017654 × 10^2 = 0,001017654 × 10^5
Следовательно: 123456,7 + 101,7654 = (1,234567 × 10^5) + (1,017654 × 10^2) = (1,234567 × 10^5) + (0,001017654 × 10^5) = (1,234567 + 0,001017654) × 10^5 = 1,235584654 × 10^5
Подробно:
е=5; с=1,234567 (123456,7)+ е=2; с=1,017654 (101,7654)
е=5; с=1,234567+ e=5; s=0,001017654 (после сдвига)-------------------- e=5; s=1,235584654 (истинная сумма: 123558,4654)
Это истинный результат, точная сумма операндов. Он будет округлен до семи цифр, а затем нормализован, если необходимо. Окончательный результат:
е=5; s=1,235585 (конечная сумма: 123558,5)
Три младшие цифры второго операнда (654) по сути теряются. Это ошибка округления . В крайних случаях сумма двух ненулевых чисел может быть равна одному из них:
е=5; с=1,234567+ е=−3; с=9,876543
е=5; с=1,234567+ e=5; s=0,00000009876543 (после сдвига)---------------------- e=5; s=1,23456709876543 (истинная сумма) e=5; s=1,234567 (после округления и нормализации)
В приведенных выше концептуальных примерах может показаться, что сумматору необходимо предоставить большое количество дополнительных цифр для обеспечения правильного округления; однако для двоичного сложения или вычитания с использованием аккуратных методов реализации необходимо вынести за пределы точности операндов только защитный бит, бит округления и один дополнительный липкий бит. [43] [44] : 218–220
Другая проблема потери значимости возникает, когда вычитаются приближения к двум почти равным числам. В следующем примере e = 5; s = 1,234571 и e = 5; s = 1,234567 являются приближениями к рациональным числам 123457,1467 и 123456,659.
е=5; с=1,234571− е=5; с=1,234567---------------- е=5; с=0,000004 e=−1; s=4.000000 (после округления и нормализации)
Разница с плавающей точкой вычисляется точно, потому что числа близки — лемма Стербенца гарантирует это, даже в случае потери значимости, когда поддерживается постепенная потеря значимости . Несмотря на это, разница исходных чисел составляет e = −1; s = 4,877000, что отличается более чем на 20% от разницы e = −1; s = 4,000000 приближений. В крайних случаях все значимые цифры точности могут быть потеряны. [43] [45] Это сокращение иллюстрирует опасность предположения, что все цифры вычисленного результата имеют смысл. Борьба с последствиями этих ошибок является темой численного анализа ; см. также Проблемы точности.
При умножении мантиссы перемножаются, показатели степеней складываются, а результат округляется и нормализуется.
е=3; с=4,734612× е=5; s=5,417242----------------------- e=8; s=25,648538980104 (истинное произведение) е=8; s=25,64854 (после округления) e=9; s=2,564854 (после нормализации)
Аналогично деление выполняется путем вычитания показателя степени делимого из показателя делителя и деления мантиссы делимого на мантиссу делителя.
При умножении или делении не возникает проблем с отменой или поглощением, хотя небольшие ошибки могут накапливаться по мере последовательного выполнения операций. [43] На практике способ выполнения этих операций в цифровой логике может быть довольно сложным (см. алгоритм умножения Бута и алгоритм деления ). [nb 9]
Литералы для чисел с плавающей точкой зависят от языка. Обычно они используют e
или E
для обозначения научной нотации . Язык программирования C и стандарт IEEE 754 также определяют синтаксис шестнадцатеричного литерала с показателем степени по основанию 2 вместо 10. В таких языках, как C , когда десятичная экспонента опущена, десятичная точка необходима для их отличия от целых чисел. В других языках нет целочисленного типа (например, JavaScript ) или допускается перегрузка числовых типов (например, Haskell ). В этих случаях строки цифр, такие как , 123
также могут быть литералами с плавающей точкой.
Примеры литералов с плавающей точкой:
99.9
-5000.12
6.02e23
-3e-45
0x1.fffffep+127
в C и IEEE 754Вычисления с плавающей точкой на компьютере могут привести к трем видам проблем:
До появления стандарта IEEE такие условия обычно приводили к завершению программы или запускали своего рода ловушку , которую программист мог бы поймать. То, как это работало, зависело от системы, что означало, что программы с плавающей точкой не были переносимыми . (Термин «исключение», используемый в IEEE 754, является общим термином, означающим исключительное состояние, которое не обязательно является ошибкой, и отличается от того, что обычно определяется в языках программирования, таких как C++ или Java, в которых « исключение » является альтернативным потоком управления, ближе к тому, что называется «ловушкой» в терминологии IEEE 754.)
Здесь обсуждается требуемый метод обработки исключений по умолчанию в соответствии с IEEE 754 (необязательное перехватывание IEEE 754 и другие режимы «альтернативной обработки исключений» не обсуждаются). Арифметические исключения (по умолчанию) должны быть записаны в «липкие» биты флага состояния. То, что они «липкие», означает, что они не сбрасываются следующей (арифметической) операцией, а остаются установленными до явного сброса. Таким образом, использование «липких» флагов позволяет отложить проверку исключительных условий до завершения полного выражения с плавающей точкой или подпрограммы: без них исключительные условия, которые иначе нельзя было бы игнорировать, потребовали бы явной проверки сразу после каждой операции с плавающей точкой. По умолчанию операция всегда возвращает результат в соответствии со спецификацией, не прерывая вычислений. Например, 1/0 возвращает +∞, а также устанавливает бит флага деления на ноль (это значение по умолчанию ∞ предназначено для частого возврата конечного результата при использовании в последующих операциях, поэтому его можно безопасно игнорировать).
Однако исходный стандарт IEEE 754 не рекомендовал операции для обработки таких наборов битов флагов арифметических исключений. Поэтому, хотя они были реализованы в оборудовании, изначально реализации языков программирования обычно не предоставляли средств для доступа к ним (кроме ассемблера). Со временем некоторые стандарты языков программирования (например, C99 /C11 и Fortran) были обновлены, чтобы указать методы доступа и изменения битов флагов состояния. Версия стандарта IEEE 754 2008 года теперь указывает несколько операций для доступа и обработки битов флагов арифметических действий. Модель программирования основана на одном потоке выполнения, и их использование несколькими потоками должно обрабатываться средствами вне стандарта (например, C11 указывает, что флаги имеют локальное хранилище потока ).
IEEE 754 определяет пять арифметических исключений, которые должны быть записаны во флагах состояния («липкие биты»):
Возвращаемое значение по умолчанию для каждого исключения предназначено для предоставления правильного результата в большинстве случаев, так что исключения можно игнорировать в большинстве кодов. inexact возвращает правильно округленный результат, а underflow возвращает значение, меньшее или равное наименьшему положительному нормальному числу по величине и почти всегда может быть проигнорировано. [46] delegate-by-zero возвращает бесконечность точно, что обычно затем делит конечное число и, таким образом, дает ноль, или же впоследствии дает недопустимое исключение, если нет, и поэтому также может быть обычно проигнорировано. Например, эффективное сопротивление n резисторов, соединенных параллельно (см. рис. 1), определяется как . Если возникает короткое замыкание с установленным значением 0, вернет +infinity, что даст окончательное значение 0, как и ожидалось [47] (см. пример непрерывной дроби в обосновании конструкции IEEE 754 для другого примера).
Переполнение и недопустимые исключения обычно не могут игнорироваться, но не обязательно представляют собой ошибки: например, процедура поиска корня в рамках своей нормальной работы может оценивать переданную функцию при значениях за пределами ее домена, возвращая NaN и недопустимый флаг исключения, который следует игнорировать до тех пор, пока не будет найдена полезная начальная точка. [46]
Тот факт, что числа с плавающей точкой не могут точно представлять все действительные числа, и что операции с плавающей точкой не могут точно представлять истинные арифметические операции, приводит ко многим удивительным ситуациям. Это связано с конечной точностью, с которой компьютеры обычно представляют числа.
Например, десятичные числа 0,1 и 0,01 не могут быть представлены точно как двоичные числа с плавающей точкой. В формате IEEE 754 binary32 с его 24-битной мантиссой результат попытки возвести в квадрат приближение к 0,1 не является ни 0,01, ни представимым числом, ближайшим к нему. Десятичное число 0,1 представлено в двоичном виде как e = −4 ; s = 110011001100110011001101 , что равно
Возведение этого числа в квадрат дает
Возведение в квадрат с округлением до 24-битной точности дает
Но представимое число, ближайшее к 0,01, это
Кроме того, непредставимость π (и π/2) означает, что попытка вычисления tan(π/2) не даст результата бесконечности, и даже не переполнит обычные форматы с плавающей точкой (предполагая точную реализацию tan). Просто невозможно для стандартного оборудования с плавающей точкой попытаться вычислить tan(π/2), потому что π/2 не может быть представлено точно. Это вычисление на языке C:
/* Достаточно цифр, чтобы убедиться, что мы получаем правильное приближение. */ double pi = 3.1415926535897932384626433832795 ; double z = tan ( pi / 2.0 );
даст результат 16331239353195370.0. При одинарной точности (с использованием tanf
функции) результат будет −22877332.0.
По той же причине попытка вычисления sin(π) не даст ноль. Результат будет (приблизительно) 0,1225 × 10 −15 в двойной точности или −0,8742 × 10 −7 в одинарной точности. [nb 10]
Хотя сложение и умножение с плавающей точкой являются коммутативными ( a + b = b + a и a × b = b × a ), они не обязательно ассоциативны . То есть, ( a + b ) + c не обязательно равно a + ( b + c ) . Использование 7-значной значащей десятичной арифметики:
а = 1234,567, б = 45,67834, в = 0,0004
(а + б) + в: 1234.567 (а) + 45.67834 (б) ____________ 1280.24534 округляется до 1280.245
1280,245 (а + б) + 0,0004 (с) ____________ 1280,2454 округляется до 1280,245 ← (a + b) + c
а + (б + в): 45.67834 (б) + 0,0004 (с) ____________ 45.67874
1234.567 (а) + 45.67874 (б + в) ____________ 1280,24574 округляется до 1280,246 ← a + (b + c)
Они также не обязательно являются дистрибутивными . То есть, ( a + b ) × c может не совпадать с a × c + b × c :
1234,567 × 3,333333 = 4115,223 1,234567 × 3,333333 = 4,115223 4115,223 + 4,115223 = 4119,338 но 1234,567 + 1,234567 = 1235,802 1235,802 × 3,333333 = 4119,340
Помимо потери значимости, невозможности точного представления таких чисел, как π и 0,1, и других незначительных неточностей, могут возникнуть следующие явления:
Интуитивно хотелось бы , чтобы h было очень близко к нулю; однако при использовании операций с плавающей точкой наименьшее число не даст наилучшего приближения производной. По мере того, как h становится меньше, разница между f ( a + h ) и f ( a ) становится меньше, отменяя самые значимые и наименее ошибочные цифры и делая наиболее ошибочные цифры более важными. В результате наименьшее возможное число h даст более ошибочное приближение производной, чем несколько большее число. Это, пожалуй, самая распространенная и серьезная проблема точности.
Машинная точность — это величина, характеризующая точность системы с плавающей точкой, и используемая в обратном анализе ошибок алгоритмов с плавающей точкой. Она также известна как округление единиц или машинный эпсилон . Обычно обозначается Ε mach , ее значение зависит от конкретного используемого округления.
С округлением до нуля, тогда как округление до ближайшего, где B — основание системы, а P — точность мантиссы (в основании B ).
Это важно, поскольку ограничивает относительную погрешность представления любого ненулевого действительного числа x в нормализованном диапазоне системы с плавающей точкой:
Анализ обратных ошибок, теория которого была разработана и популяризирована Джеймсом Х. Уилкинсоном , может быть использован для установления того, что алгоритм, реализующий числовую функцию, численно устойчив. [52] Основной подход заключается в том, чтобы показать, что хотя вычисленный результат из-за ошибок округления не будет точно правильным, он является точным решением близлежащей проблемы со слегка возмущенными входными данными. Если требуемое возмущение мало, порядка неопределенности во входных данных, то результаты в некотором смысле настолько точны, насколько «заслуживают» данные. Тогда алгоритм определяется как обратно устойчивый . Устойчивость является мерой чувствительности к ошибкам округления данной числовой процедуры; напротив, число условий функции для данной задачи указывает на присущую функции чувствительность к малым возмущениям во входных данных и не зависит от реализации, используемой для решения проблемы. [53]
В качестве тривиального примера рассмотрим простое выражение, дающее скалярное произведение векторов (длины два) и , тогда и так далее.
где
где
по определению, что является суммой двух слегка возмущенных (порядка Ε mach ) входных данных, и поэтому обратно устойчиво. Для более реалистичных примеров в числовой линейной алгебре см. Higham 2002 [54] и другие ссылки ниже.
Хотя отдельные арифметические операции IEEE 754 гарантированно точны в пределах половины ULP , более сложные формулы могут страдать от больших ошибок по разным причинам. Потеря точности может быть существенной, если задача или ее данные плохо обусловлены , что означает, что правильный результат сверхчувствителен к крошечным возмущениям в ее данных. Однако даже хорошо обусловленные функции могут страдать от большой потери точности, если используется алгоритм, численно нестабильный для этих данных: внешне эквивалентные формулировки выражений на языке программирования могут заметно отличаться по своей численной устойчивости. Одним из подходов к устранению риска такой потери точности является разработка и анализ численно устойчивых алгоритмов, что является целью раздела математики, известного как численный анализ . Другой подход, который может защитить от риска численной нестабильности, — это вычисление промежуточных (рабочих) значений в алгоритме с более высокой точностью, чем требуется для конечного результата, [55] что может устранить или уменьшить на порядки [56] такой риск: четверная точность и расширенная точность IEEE 754 предназначены для этой цели при вычислениях с двойной точностью. [57] [примечание 11]
Например, следующий алгоритм представляет собой прямую реализацию для вычисления функции A ( x ) = ( x −1) / (exp( x −1) − 1) , которая хорошо обусловлена при 1,0, [примечание 12] однако можно показать, что она численно нестабильна и теряет до половины значащих цифр, переносимых арифметикой, при вычислении вблизи 1,0. [58]
двойной А ( двойной Х ) { двойной Y , Z ; // [1] Y = X - 1,0 ; Z = ехр ( Y ); если ( Z != 1.0 ) Z = Y / ( Z - 1,0 ); // [2] вернуть Z ; }
Однако если все промежуточные вычисления выполняются с повышенной точностью (например, путем установки строки [1] в значение C99 long double
), то можно поддерживать полную точность в конечном результате double. [nb 13] В качестве альтернативы численный анализ алгоритма показывает, что если сделать следующее неочевидное изменение в строке [2]:
Z = log ( Z ) / ( Z - 1,0 );
тогда алгоритм становится численно устойчивым и может выполнять вычисления с полной двойной точностью.
Для поддержания свойств таких тщательно сконструированных численно устойчивых программ требуется осторожное обращение со стороны компилятора . Определенные «оптимизации», которые могут выполнять компиляторы (например, переупорядочивание операций), могут работать против целей хорошо работающего программного обеспечения. Существуют некоторые разногласия относительно недостатков компиляторов и дизайна языков в этой области: C99 является примером языка, где такие оптимизации тщательно определены для поддержания числовой точности. См. внешние ссылки в конце этой статьи.
Подробное рассмотрение методов написания высококачественного программного обеспечения с плавающей точкой выходит за рамки этой статьи, и читатель может обратиться к [54] [59] и другим ссылкам в конце этой статьи. Кахан предлагает несколько практических правил, которые могут существенно снизить на порядки [59] риск числовых аномалий, в дополнение к или вместо более тщательного численного анализа. К ним относятся: как отмечено выше, вычисление всех выражений и промежуточных результатов с наивысшей точностью, поддерживаемой оборудованием (общее практическое правило заключается в том, чтобы переносить в два раза большую точность желаемого результата, т. е. вычислять с двойной точностью для конечного результата с одинарной точностью или с двойной расширенной или учетверенной точностью для результатов вплоть до двойной точности [60] ); и округление входных данных и результатов только до точности, требуемой и поддерживаемой входными данными (перенос избыточной точности в конечный результат сверх требуемой и поддерживаемой входными данными может вводить в заблуждение, увеличивает стоимость хранения и снижает скорость, а избыточные биты могут повлиять на сходимость числовых процедур: [61] в частности, первая форма итеративного примера, приведенного ниже, сходится правильно при использовании этого эмпирического правила). Далее следуют краткие описания нескольких дополнительных проблем и методов.
Поскольку десятичные дроби часто не могут быть точно представлены в двоичном формате с плавающей точкой, такая арифметика лучше всего подходит, когда она просто используется для измерения реальных величин в широком диапазоне масштабов (например, период обращения луны вокруг Сатурна или масса протона ) , а хуже всего — когда от нее ожидается моделирование взаимодействия величин, выраженных в виде десятичных строк, которые, как ожидается, будут точными. [56] [59] Примером последнего случая являются финансовые расчеты. По этой причине финансовое программное обеспечение, как правило, не использует двоичное представление чисел с плавающей точкой. [62] Тип данных «decimal» языков программирования C# и Python и десятичные форматы стандарта IEEE 754-2008 разработаны для того, чтобы избежать проблем двоичных представлений с плавающей точкой при применении к введенным человеком точным десятичным значениям и заставить арифметику всегда вести себя так, как ожидается, когда числа печатаются в десятичном формате.
Ожидания от математики могут не оправдаться в области вычислений с плавающей точкой. Например, известно, что , и что , однако на эти факты нельзя полагаться, когда задействованные величины являются результатом вычислений с плавающей точкой.
Использование теста на равенство ( if (x==y) ...
) требует осторожности при работе с числами с плавающей точкой. Даже простые выражения, такие как 0.6/0.2-3==0
will, на большинстве компьютеров не будут истинными [63] (например, в IEEE 754 двойная точность 0.6/0.2 - 3
приблизительно равна -4,44089209850063e-16). Следовательно, такие тесты иногда заменяются «нечеткими» сравнениями ( if (abs(x-y) < epsilon) ...
, где epsilon достаточно мал и адаптирован к приложению, например, 1,0E−13). Разумность этого действия сильно различается и может потребовать численного анализа для ограничения epsilon. [54] Значения, полученные из первичного представления данных, и их сравнения должны выполняться с более широкой, расширенной точностью, чтобы минимизировать риск таких несоответствий из-за ошибок округления. [59] Часто лучше организовать код таким образом, чтобы такие тесты были ненужными. Например, в вычислительной геометрии точные проверки того, лежит ли точка вне или на линии или плоскости, определяемой другими точками, могут быть выполнены с использованием методов адаптивной точности или точной арифметики. [64]
Небольшие ошибки в арифметике с плавающей точкой могут расти, когда математические алгоритмы выполняют операции огромное количество раз. Несколько примеров — это обращение матрицы , вычисление собственного вектора и решение дифференциальных уравнений. Эти алгоритмы должны быть очень тщательно разработаны, с использованием численных подходов, таких как итеративное уточнение , если они должны работать хорошо. [65]
Суммирование вектора значений с плавающей точкой является базовым алгоритмом в научных вычислениях , поэтому понимание того, когда может произойти потеря значимости, имеет важное значение. Например, если складывается очень большое количество чисел, отдельные слагаемые очень малы по сравнению с суммой. Это может привести к потере значимости. Типичное сложение будет выглядеть примерно так:
3253.671+ 3.141276-----------3256.812
Нижние 3 цифры слагаемых фактически теряются. Предположим, например, что нужно сложить много чисел, все из которых приблизительно равны 3. После сложения 1000 из них текущая сумма составляет около 3000; потерянные цифры не восстанавливаются. Алгоритм суммирования Кахана может быть использован для уменьшения ошибок. [54]
Ошибка округления может повлиять на сходимость и точность итеративных численных процедур. Например, Архимед аппроксимировал π, вычисляя периметры многоугольников, вписывающих и описывающих окружность, начиная с шестиугольников и последовательно удваивая число сторон. Как отмечено выше, вычисления можно перестроить таким образом, чтобы это было математически эквивалентно, но менее подвержено ошибкам ( численный анализ ). Две формы рекуррентной формулы для описанного многоугольника: [ необходима цитата ]
Ниже приведено вычисление с использованием арифметики IEEE «double» (значащая часть с точностью 53 бита):
i 6 × 2 i × t i , первая форма 6 × 2 i × t i , вторая форма-------------------------------------------------- ------- 0 3 .4641016151377543863 3 .4641016151377543863 1 3 .2153903091734710173 3 .2153903091734723496 2 3.1 596599420974940120 3.1 596599420975006733 3 3,14 60862151314012979 3,14 60862151314352708 4 3,14 27145996453136334 3,14 27145996453689225 5 3.141 8730499801259536 3.141 8730499798241950 6 3.141 6627470548084133 3.141 6627470568494473 7 3.141 6101765997805905 3.141 6101766046906629 8 3.14159 70343230776862 3.14159 70343215275928 9 3.14159 37488171150615 3.14159 3748771353666810 3.141592 9278733740748 3.141592 927385097988511 3.141592 7256228504127 3.141592 722038614837712 3.1415926 717412858693 3.1415926 70701999212513 3.1415926 189011456060 3.14159265 7867845472814 3.1415926 717412858693 3.14159265 4659307370915 3.14159 19358822321783 3.141592653 857173011916 3.1415926 717412858693 3.141592653 656639422217 3.1415 810075796233302 3.141592653 606506191318 3.1415926 717412858693 3.1415926535 93972883619 3.141 4061547378810956 3.1415926535 90839390120 3.14 05434924008406305 3.1415926535 90056016821 3.14 00068646912273617 3.141592653589 860839622 3,1 349453756585929919 3.141592653589 812211823 3,14 00068646912273617 3,14159265358979 9555224 3 .2245152435345525443 3.14159265358979 6890725 3.14159265358979 6224626 3.14159265358979 6224627 3.14159265358979 6224628 3.14159265358979 62246 Истинное значение равно 3,14159265358979323846264338327...
Хотя обе формы формулы повторения явно математически эквивалентны, [nb 14] первая вычитает 1 из числа, чрезвычайно близкого к 1, что приводит к все более проблематичной потере значащих цифр . Поскольку повторение применяется повторно, точность сначала улучшается, но затем ухудшается. Она никогда не становится лучше, чем около 8 цифр, хотя 53-битная арифметика должна быть способна к точности около 16 цифр. Когда используется вторая форма формулы повторения, значение сходится к 15 цифрам точности.
Вышеупомянутое отсутствие ассоциативности операций с плавающей точкой в целом означает, что компиляторы не могут так же эффективно переупорядочивать арифметические выражения, как они могли бы с целочисленной и фиксированной арифметикой, что представляет собой препятствие для оптимизаций, таких как устранение общих подвыражений и автовекторизация . [ 66] Опция «быстрой математики» во многих компиляторах (ICC, GCC, Clang, MSVC...) включает повторную ассоциацию вместе с небезопасными предположениями, такими как отсутствие NaN и бесконечных чисел в IEEE 754. Некоторые компиляторы также предлагают более детальные опции, чтобы включить только повторную ассоциацию. В любом случае программист подвергается многим подводным камням точности, упомянутым выше для части программы, использующей «быструю» математику. [67]
В некоторых компиляторах (GCC и Clang) включение «быстрой» математики может привести к отключению программой субнормальных чисел с плавающей точкой при запуске, что повлияет на поведение чисел с плавающей точкой не только сгенерированного кода, но и любой программы, использующей такой код в качестве библиотеки . [68]
В большинстве компиляторов Fortran , как разрешено стандартом ISO/IEC 1539-1:2004 Fortran, повторная ассоциация является значением по умолчанию, а ее разрушение в значительной степени предотвращается настройкой «protect parens» (также включенной по умолчанию). Эта настройка не позволяет компилятору повторно ассоциировать данные за пределами скобок. [69] Компилятор Intel Fortran является заметным исключением. [70]
Распространенной проблемой в «быстрой» математике является то, что подвыражения могут не оптимизироваться одинаково от места к месту, что приводит к неожиданным различиям. Одной из интерпретаций проблемы является то, что «быстрая» математика, как она реализована в настоящее время, имеет плохо определенную семантику. Одна из попыток формализовать «быстрые» математические оптимизации наблюдается в Icing , проверенном компиляторе. [71]
[…] Такие системы, как [Digital Field System] DFS IV и DFS V, были четверичными системами с плавающей запятой и использовали шаг усиления 12 дБ. […](256 страниц)
[…] плавающее основание Maniac, которое равно 2
16
= 65 536. […] Большое основание Maniac позволяет значительно увеличить скорость арифметики с плавающей точкой. Хотя такое большое основание подразумевает возможность до 15 ведущих нулей, большой размер слова в 48 бит гарантирует адекватную значимость. […]
«Расширенный» — это двойной расширенный формат данных IEC 60559. Расширенный относится как к обычному 80-битному, так и к учетверенному 128-битному формату IEC 60559.
Поскольку спецификация IEEE-754 с плавающей точкой не определяет 16-битный формат, ILM создал формат "half". Значения half имеют 1 бит знака, 5 бит экспоненты и 10 бит мантиссы.
[…] _fmsbintoieee(float *src4, float *dest4) […] Формат MS Binary […] порядок байтов => m3 | m2 | m1 | экспонента […] m1 —
старший байт
=> sbbb|bbbb […] m3 —
младший байт
[…] m = байт мантиссы […] s = знаковый бит […] b = бит […] MBF имеет смещение 128, а IEEE — смещение 127. […] MBF помещает
десятичную точку
перед
предполагаемым битом
, тогда как IEEE помещает десятичную точку после предполагаемого бита. […] ieee_exp = msbin[3] - 2; /* на самом деле, msbin[3]-1-128+127 */ […] _dmsbintoieee(double *src8, double *dest8) […] Двоичный формат MS […] порядок байтов => m7 | m6 | m5 | m4 | m3 | m2 | m1 | экспонента […] m1 — старший байт => smmm|mmmm […] m7 — младший байт […] MBF имеет смещение 128, а IEEE — смещение 1023. […] MBF помещает десятичную точку перед предполагаемым битом, тогда как IEEE помещает десятичную точку после предполагаемого бита. […] ieee_exp = msbin[7] - 128 - 1 + 1023; […]
Гораздо более тревожной является ошибка отмены, которая может привести к катастрофической потере точности.[4]
Мы поддерживаем операции редукции с плавающей точкой при использовании -ffast-math.