У меня есть калькулятор времени, который работал довольно хорошо в течение ряда лет. Однако меня всегда беспокоило то, что если использовать доли секунды, результаты станут жертвами «ошибок» с плавающей запятой. Итак, я недавно переключился на использование этой библиотеки BigDecimal .
Теперь я получаю математические ошибки. Вот упрощенный тестовый пример из отчета об ошибке, который я получил сегодня: 27436 / 30418
возвращает 1
вместо ожидаемого 0.9019659412190151
.
Чтобы проиллюстрировать мою проблему, вот консольный сеанс Javascript в Chrome:
> first = 27436
27436
> second = 30418
30418
> first / second
0.9019659412190151 // expected result, but using JS numbers, not BigDecimals
> firstB = new BigDecimal(first.toString())
o
> secondB = new BigDecimal(second.toString())
o
> firstB / secondB
0.9019659412190151 // this is a JS number, not a BigDecimal, so it's susceptible to the problems associated with floating-point.
> firstB.divide(secondB)
o // BigDecimal object
> firstB.divide(secondB).toString()
"1" // huh? Why 1?
> firstB.divideInteger(secondB).toString()
"0"
Как видите, метод divide()
не дает ожидаемого результата. Что мне нужно сделать по-другому?
Обновление
Вот некоторые подробности в ответ на комментарии.
Во-первых, несколько человек предположили, что использование BigDecimal было излишним. Это может быть, но я думаю, что необходимо больше подробностей, прежде чем принимать это решение. Это приложение Калькулятор времени , поэтому есть пара вещей, которые подтолкнули меня к переходу на BigDecimal. Во-первых, поскольку это калькулятор, важно показать пользователю правильный ответ. Если пользователь вводит 0.1 s + 0.2 s
, он ожидает, что ответом будет 0.3 s
, а не ответ, который Javascript покажет им (0.30000000000000004
).
Я действительно не хочу ограничивать точность сверх того, что я могу использовать в JS, чтобы я мог использовать целые числа, потому что я не знаю максимальной точности, которая нужна моим пользователям. Я думаю, что большинство из них никогда не используют доли секунды, но, судя по полученному мною электронному письму, некоторые используют. В настоящее время я храню все время как секунды.
Кто-то предложил мне хранить числа как точные дроби. К сожалению, я не знаю, что это значит. Возможно, это потому, что я мало знаю о математике. Я не знаю достаточно, чтобы свернуть мою собственную математическую библиотеку; Вот почему я использую BigDecimal. Это было давно, поэтому я не решаюсь сказать, что моя проблема из-за ошибки в BigDecimal. Я скорее подозреваю, что это ошибка в том, как я ее использую.
Наконец, я специально не привязан к BigDecimal. Я открыт для других предложений, при условии, что я могу использовать их с моими недостаточными математическими навыками.