*Все примеры здесь рассматриваются для 64 битных чисел(все примеры аналогичны и для других значений), если не указано иное.
Более 90% всех программистов знают, что такое обычные числа с плавающей запятой: binary32/binary64/binary128, их часто называют float, double и т.д. соответсвенно, есть много информации о том почему 0,1 не может существовать в бинарном виде, что при большом количестве значащих цифр будут недостаток точности, даже, если ты не выходишь за рамки 16 цифр, зато они быстрые… Но почти нет информации о том, что прекрасное решение, которое сохраняет все достоинства и исправляет недостатки, есть, даже в самом обновленном стандарте плавающих чисел IEEE 754-2008 уже больше 15 лет, это decimal floating point(DFP).
Для начала вспомним устройство обычного binary64: 1 бит знака, 11 битов экспоненты, 52 бита мантиссы. Давайте лучше картинку покажу:
Раньше попытка создать десятичную систему для плавающих чисел привела к прожорливому, которому, чем больше памяти дашь, тем больше он съест BCD, ты кодировал числа тетрадами, но главная проблема это, то что четвертый бит использовался лишь для трёх чисел, из-за этого даже двоичная мантисса для иррациональных чисел была точнее, так как позволяла кодировать больше десятичных цифр: 16,3 против 13.
Потеря битов была замечена в конце 1960-х, поэтому была создана кодировка Чен-Хо, которая кодировала 3 десятичные цифры в 10 битов, после 2002 году её доработали и превратили в плотно упакованную десятичную дробь или правильнее Densely packed decimal(DPD) были сохранены все преимущества и добавлено ещё одно первые числа в этой кодировке были такими же, как в BCD, это упрощало преобразования, поэтому её включили в обновленный стандарт IEEE 754, там же оказалась ещё одна Binary Integer Decimal(BID). Потери были хоть какими-то в этом случае только для 10 байтов: 1000 против 1024 десятичных цифр, но покажите мне реальное применение таких чисел с 80 битами в мантиссе(!).
Вот иллюстрация кодирования цифр в BCD, Чен-Хо, DPD:
Кодировка есть, плавающие числа есть, так что же не объединить? Это и было сделано: мы получили Decimal floating-point (DFP), в них может использоваться DPD, либо BID(разницы особо нет).
Давайте проведём сравнение binary64 vs decimal64(для остальных вариантов всё будет аналогично):
-
Количество значащих цифр 16,3 и 16 — паритет.
-
Диапазон экспоненты 10−308 до 10308 и 10−383 до 10384 — здесь победа Decimal64.
-
Скорость выполнения: Первый ответ, который приходит в голову — binary быстрее. Но тут очень интересно: binary считает не ALU(он просто не умеет) а отдельный подпроцессор(FPU), поэтому тоже самое можно сделать и для Decimal(сейчас есть реализация только в микрокоде). Это как сравнивать двоичные и троичные компьютеры при этом вторые эмулировать программно. Паритет.
Итог: Decimal floating point очень интересная и выгодная из-за возможности представить точно десятичную систему счисления замена binary, реализовать её не сложнее FPU, а плюсов будет больше. Почему не заменили в ПК(моё мнение): хоть она и есть в IEEE 754, мало кому она известна, а производителям процессора для ПК лень менять, так как запроса нет, а запроса нет, потому что нет реализаций и даже в C++ нет Decimal, получается замкнутый круг. Но это моё мнение, я буду рад прочитать комментарии, которые дадут другую точку зрения, их плюсы и минусы Decimal, и почему нет аппаратной реализации в персональных компьютерах.
Цель этой статьи познакомить большее количество людей с этой удивительной технологией, поэтому без большого количества формул и т.п. :).