РуководстваПочему конвертеры с плавающей запятой не работают (и как это исправляет десятичная математика)
Почему конвертеры с плавающей запятой не работают (и как это исправляет десятичная математика)
Узнайте, почему двоичные операции с плавающей запятой создают странные остатки преобразования, когда эти ошибки имеют значение и как десятичная или рациональная арифметика обеспечивает надежность конвертеров единиц измерения.
Классическая задача 0,1+0,2 соответствует единицам
Большинство процессоров хранят нецелые числа в двоичном формате с плавающей запятой (IEEE 754). Дроби, которые выглядят просто в десятичном формате — 0,1, 0,001, 2,54 — часто не могут быть точно представлены в двоичном виде. Сохраненное значение представляет собой ближайшее представимое приближение, а арифметика приближений накапливает крошечные остатки.
Преобразование единиц многократно умножает и делит эти значения. Переведите дюймы в миллиметры и обратно или литры в кубические метры и обратно, и вы увидите 2,9999999997 вместо 3. Физический коэффициент перевода был точным; компьютерного представления не было.
Для многих дисплеев разница после округления не видна. Для дозирования, связанного с финансами, траекторий движения инструмента с ЧПУ, законной площади земли или утверждений автоматических испытаний, ожидающих точного равенства, эти остатки становятся настоящими ошибками.
Какие коэффициенты пересчета точны на бумаге
Международный дюйм равен ровно 25,4 мм. Международный фут равен ровно 0,3048 м. Литр равен ровно 0,001 м³. Кубический сантиметр равен ровно 1 мл в обычном лабораторном понимании (1 см³ = 10⁻⁶ м³). Это определения, а не измерения.
Если программное обеспечение хранит число 25,4 как двоичное число с плавающей запятой, оно может быть немного неверным еще до начала преобразования. Умножение на другой неточный коэффициент усугубляет ошибку. Тесты туда и обратно, которые утверждают строгое равенство, затем терпят неудачу, даже если алгоритм концептуально верен.
Температура добавляет смещения: по Цельсию ↔ Кельвину используется 273,15. Эта константа также является десятичной величиной, которую двоичные числа с плавающей запятой лишь приблизительно оценивают. Аффинные преобразования особенно чувствительны, поскольку добавление неточного смещения меняет каждый результат.
Где на практике проявляются ошибки с плавающей запятой
Преобразователи пользовательского интерфейса часто скрывают проблему, округляя до фиксированного числа десятичных знаков. Пользователи видят чистые результаты и никогда не замечают внутреннего шума. Проблемы возникают, когда другая система использует необработанное число с плавающей запятой: ядро САПР, экспорт CSV или модульный тест, сравнивающий строки полной точности.
Связанные преобразования усугубляют проблемы. Переход миля → ярд → фут → дюйм → миллиметр → метр с двоичными числами с плавающей запятой на каждом шаге хуже, чем преобразование одной мили → метр с коэффициентом высокой точности. Каждый переход повторно округляет промежуточное значение.
Величины, возведенные в квадрат и куб, усугубляют ошибки. Площадь и объем умножают масштабы длины, поэтому небольшая относительная ошибка длины становится в два или три раза больше в относительном выражении площади или объема при расширении (1+ε)ⁿ.
Десятичные, рациональные альтернативы и альтернативы с фиксированной запятой
Библиотеки десятичных дробей (например, decimal.js, Big.js или собственные десятичные дроби) хранят числа в десятичной системе счисления. Точные десятичные множители, такие как 0,3048 и 0,001, остаются точными в пределах выбранной точности. Конвертеры единиц измерения, которые заботятся о правильности, часто выполняют преобразование через десятичную базовую единицу.
Рациональная арифметика хранит факторы как дроби целых чисел. Если 1 дюйм = ровно 127/5000 метров (поскольку 25,4 мм = 127/5000 м), умножение можно отменить точно. Rational идеально подходят для преобразований в чистом масштабе; смещения по-прежнему требуют осторожного обращения с температурой.
Математика с фиксированной запятой масштабирует все до целого числа наименьшего тика — нанометров, микролитров или тысячных долей дюйма. Целочисленная арифметика точна до тех пор, пока вы не переполнитесь. Это хорошо работает для областей с четким объемом измерения.
Практические правила для надежных преобразователей
Храните точные юридические коэффициенты в виде десятичных или рациональных чисел, а не в виде наспех набранных двоичных чисел с плавающей запятой. Преобразуйте входные данные → базовые → выходные данные за минимальное количество шагов. Округляйте только при форматировании для людей и документируйте режим округления.
Никогда не тестируйте преобразователи со строгим равенством двоичных чисел с плавающей запятой. Сравнивайте в пределах абсолютного или относительного допуска или сравнивайте формы десятичных строк с указанной точностью. Отдавайте предпочтение золотым тестам, в которых используются известные точные пары, например 1 дюйм = 25,4 мм.
Если вы создаете пользовательский интерфейс калькулятора, покажите достаточную точность, чтобы быть полезным, но не так много цифр, чтобы плавающий шум выглядел как сигнал. Инструмент длины, показывающий двенадцать десятичных знаков после преобразования через числа с плавающей запятой, сообщает об ошибке представления.
Когда двоичные числа с плавающей запятой все еще в порядке
Грубые сравнения, игры, визуализация данных и многие научные симуляции допускают ошибку с плавающей запятой, поскольку неопределенность модели затмевает ошибку представления. Ключ в том, чтобы знать свою толерантность. Если миллиметр имеет значение, поплавки требуют дисциплины или замены.
Аппаратное ускорение и конвейеры графического процессора часто приводят к принудительному плаванию. В таких случаях сохраняйте достоверное преобразование в десятичное число на ЦП или сервере и рассматривайте числа с плавающей запятой на графическом процессоре как отображаемое или промежуточное приближение.
Хорошая инженерия — это сопоставление числового представления с решением, которое вы примете с его помощью. Преобразование единиц измерения для производства, медицины и законодательной метрологии заслуживает десятичной или рациональной математики; виджет погоды, преобразующий городскую температуру, этого не делает. Если вы сомневаетесь, выберите более строгое представление — затраты на производительность десятичных дробей обычно меньше, чем затраты на тихую двустороннюю ошибку.
Связанные конвертеры
Часто задаваемые вопросы
Почему конвертация туда и обратно меняет мой номер?
Двоичные числа с плавающей запятой не могут точно представлять многие десятичные множители. Каждое умножение или деление добавляет небольшую ошибку округления. При двустороннем преобразовании с помощью чисел с плавающей запятой часто не удается восстановить исходные биты, даже если коэффициенты преобразования концептуально точны.
Достаточно ли двойной точности для преобразования единиц измерения?
Двойной точности (float64) достаточно для многих повседневных преобразований после округления дисплея, но она не заменяет точные десятичные множители, когда вам нужны бит-стабильные обходы, законодательная метрология или строгие автоматические тесты. Для авторитетных преобразователей отдавайте предпочтение десятичным или рациональным дробям.
Как мне сравнить результаты преобразователя в тестах?
Сравнивайте с заявленной точностью, используйте равенство десятичных строк или устанавливайте абсолютные и относительные допуски. Не ожидайте точного двоичного равенства после нескольких арифметических шагов.