Существует множество способов хранения дробных чисел, и каждый из них имеет свои преимущества и недостатки.
Плавающая точка , безусловно, самый популярный формат. Он работает, кодируя знак, мантиссу и подписанный показатель base-2 в целые числа и упаковывая их в кучу битов. Например, вы можете иметь 32-битную мантиссу 0.5
(кодированную как 0x88888888
) и 32-битную подписанную экспоненту +3
( 0x00000003
), которая будет декодировать в 4.0
(0.5 * 2 ^ 3
). Числа с плавающей запятой являются быстрыми, потому что они реализованы аппаратно, и их точность масштабируется с абсолютным размером, то есть, чем меньше число, тем выше абсолютная точность, поэтому относительная ошибка округления остается постоянной с абсолютным размером. Число с плавающей запятой отлично подходит для значений, взятых из непрерывной области, таких как длины, уровни звукового давления, уровни освещенности и т. Д., И поэтому они обычно используются при обработке звука и изображений, а также для статистического анализа и моделирования физики. Их самым большим недостатком является то, что они не являются точными, то есть они склонны к ошибкам округления и не могут точно представлять все десятичные дроби. Все основные языки программирования имеют некоторую точку плавания.
Фиксированная точкаработает с использованием достаточно больших целых чисел и неявно резервирует часть их битов для дробной части. Например, 24,8-битное число с фиксированной точкой резервирует 24 бита для целой части (включая знак) и 8 бит для дробной части. Сдвиг вправо этого числа на 8 битов дает нам целую часть. Числа с фиксированной запятой были популярны, когда аппаратные единицы с плавающей запятой были необычны или, по крайней мере, намного медленнее, чем их целочисленные аналоги. В то время как числа с фиксированной запятой несколько легче обрабатывать с точки зрения точности (хотя бы потому, что их легче рассуждать), они уступают числам с плавающей точкой практически во всех других отношениях - они имеют меньшую точность, меньший диапазон и потому, что дополнительные Операции необходимы для корректировки вычислений для неявного сдвига, сегодня математика с фиксированной запятой часто медленнее, чем математика с плавающей запятой.
Десятичные типы работают во многом как числа с плавающей запятой или числа с фиксированной запятой, но они принимают десятичную систему, то есть их показатель степени (неявный или явный) кодирует степень-10, а не степень-2. Десятичное число может, например, кодировать мантиссу 23456
и показатель степени -2
, и это расширится до234.56
, Десятичные числа, поскольку арифметика не встроена в процессор, медленнее, чем числа с плавающей запятой, но они идеальны для всего, что включает десятичные числа и требует, чтобы эти числа были точными, с округлением, происходящим в четко определенных местах - финансовые вычисления, табло и т. д. Некоторые языки программирования имеют встроенные десятичные типы (например, C #), другим требуются библиотеки для их реализации. Обратите внимание, что хотя десятичные числа могут точно представлять неповторяющиеся десятичные дроби, их точность не лучше точности чисел с плавающей запятой; выбор десятичных дробей просто означает, что вы получаете точные представления чисел, которые могут быть представлены точно в десятичной системе (точно так же, как числа с плавающей точкой могут точно представлять двоичные дроби).
Рациональные числа хранят числитель и денумератор, обычно используя некоторый тип целочисленного типа bignum (числовой тип, который может расти настолько, насколько позволяют ограничения памяти компьютера). Это единственный тип данных из множества, который может точно моделировать числа, такие как 1/3
или 3/17
, а также операции с ними - рациональные, в отличие от других типов данных, будут давать правильные результаты для таких вещей, как3 * 1/3
, Математика довольно проста, хотя придумать эффективный алгоритм факторинга довольно сложно. Некоторые языки программирования имеют встроенные рациональные типы (например, Common Lisp). Недостатки рационального подхода заключаются в том, что они медленны (многие операции требуют сокращения дробей и факторинга их компонентов) и что многие обычные операции трудно или невозможно реализовать, и большинство реализаций приведут рациональное к плавающему, когда это произойдет (например, когда вы вызываете sin()
по рациональному).
BCD (Binary Coded Decimal) использует «полубайты» (группы по 4 бита) для кодирования отдельных цифр; так как клев может содержать 16 различных значений, но десятичные числа требуют только 10, для каждого куска есть 6 «недопустимых» значений. Как и десятичные числа, числа BCD являются точными десятичными числами, то есть вычисления, выполняемые для десятичных чисел, работают так же, как если бы вы делали их с помощью ручки и бумаги. Арифметические правила для BCD несколько неуклюжи, но есть и преимущество в том, что преобразовать их в строки проще, чем в некоторых других форматах, что особенно интересно для сред с ограниченными ресурсами, таких как встроенные системы.
Строки , да, простые старые строки, также могут использоваться для представления дробных чисел. Технически, это очень похоже на BCD, только с явной десятичной точкой, и вы используете один полный байт на десятичную цифру. Таким образом, формат является расточительным (используются только 11 из 256 возможных значений), но его легче анализировать и генерировать, чем BCD. Кроме того, поскольку все используемые значения являются «не подозрительными», безвредными и не зависящими от платформы, строки в кодировке строк могут без проблем перемещаться по сетям. Нередко найти арифметику, выполняемую непосредственно над строками, но это возможно, и когда вы делаете это, они точно так же десятичны, как и другие десятичные форматы (десятичные дроби и BCD).