Lua: вычитание десятичных чисел не возвращает правильную точность - PullRequest
4 голосов
/ 27 августа 2010

Я использую Lua 5.1

print(10.08 - 10.07)

Вместо печати 0,01, над отпечатками 0,0099999999999998.

Есть идеи, как получить 0,01 от этого вычитания?

Ответы [ 4 ]

12 голосов
/ 27 августа 2010

Вы получили 0,01 от вычитания.Это просто в форме повторяющейся десятичной дроби с небольшим количеством потерянной точности.

Lua использует тип C double для представления чисел.Это почти на каждой платформе, которую вы будете использовать, 64-битное двоичное значение с плавающей запятой с точностью примерно до 23 десятичных знаков.Тем не менее, нет достаточной точности для представления 0,01 точно в двоичном виде.Ситуация похожа на попытку записать 1/3 в десятичном формате.

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

Решение зависит от вашего контекста.Если вы ведете учет, то я настоятельно рекомендую вам не использовать значения с плавающей запятой для представления значений счета, поскольку эти небольшие ошибки будут накапливаться, и в конечном итоге целые центы (или хуже) будут появляться или исчезать.Гораздо лучше хранить учетные записи в целочисленных центах и ​​делить их на 100 для отображения.

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

Некоторые ресурсы для фона:

Редактировать: В конце концов, добавлен документ WECSSKAFPA.Это действительно стоит изучения, хотя это может показаться немного подавляющим на первом проходе.В том же духе Knuth Volume 2 имеет широкий охват арифметики в целом и большой раздел с плавающей запятой.И, так как lhf напомнил мне о его существовании, я вставил вики-объяснение Lua о том, почему с плавающей запятой можно использовать в качестве единственного числового типа в качестве первого элемента в списке.

3 голосов
/ 27 августа 2010

Используйте функцию Lua string.format:

print(string.format('%.02f', 10.08 - 10.07))
1 голос
/ 27 августа 2010

Используйте библиотеку Десятичных чисел для Lua.

1 голос
/ 27 августа 2010

Использовать библиотеку произвольной точности .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...