Почему ошибка с плавающей запятой изменяется в зависимости от положения десятичной дроби?
Поскольку вы работаете с основанием 10. Двоичная с плавающей запятой двойной точности IEEE-754 работает в двоичной форме(база 2).В этом представлении, например, 1
может быть представлено точно, но 0.1
не может. ¹
Что действительно странно в этом сценарии, так это то, что эти числа находятся в пределах диапазона чисел, представляемыхплавающая запятая.Мы не имеем дело с очень большими или очень маленькими числами.
Как вы можете видеть из моего утверждения выше, даже если перейти к десятым, вы сталкиваетесь с неточными числами, не прибегая к возмутительным значениям (как вы делаете, чтобы добраться до непредставимых целых чисел, таких как 9 007 199 254 740 993).Отсюда и знаменитая 0.1 + 0.2 = 0.30000000000000004
вещь:
console.log(0.1 + 0.2);
Существует ли "более безопасный" способ умножения чисел с плавающей запятой, чтобы предотвратить эту проблему?
Не использовать встроенную функцию с плавающей запятойточка.Вы можете работать только в целых числах (так как они надежны от -9,007,199,254,740,992 до 9,007,199,254,740,992), а затем при выводе вставить соответствующий десятичный знак.Вы можете найти ответы на этот вопрос полезными: Как справиться с точностью чисел с плавающей запятой в JavaScript? .
¹ Вам может быть интересно, почему, если 0.1
не отображается точно, console.log(0.1)
выводит "0.1"
.Это происходит потому, что обычно с плавающей запятой при преобразовании в строку выводится только достаточное количество цифр, чтобы отличить число от ближайшего представимого соседа.В случае 0.1
все, что нужно, это "0.1"
.Преобразование двоичной плавающей запятой в представимое десятичное число довольно сложно, см. Различные примечания и цитаты в спецификации .: -)