Округление с плавающей точкой с ошибкой представления до ближайшего и правильного результата

У меня возникла ситуация, когда классическая ошибка представления в Python стала проблемой: мне нужно, чтобы они использовались для операций с матрицами в Numpy, а десятичный тип еще не поддерживается.

Вы все знаете, что если я сделаю 111.85 * 111.85 я получу 12510.422499999999 но если я round(12510.422499999999, 4) Я могу получить правильный результат, который, конечно, 12510.4225,

Но актуальные вопросы:

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

2 ответа

Решение

Даже если вы округлите число, десятичное число все равно будет не таким , как вы ожидаете. Python может отображать только самые значимые биты, но основная десятичная погрешность все еще там.

Документы по Python посвящают этому раздел

Многие пользователи не знают о приближении из-за способа отображения значений. Python печатает только десятичное приближение к истинному десятичному значению двоичного приближения, хранящегося на машине. На большинстве машин, если бы Python должен был печатать истинное десятичное значение двоичного приближения, сохраненного для 0.1, он должен был бы отображать

>>> 0.1
0.1000000000000000055511151231257827021181583404541015625

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

>>> 1 / 10
0.1

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

 >>> Decimal('111.85') * Decimal('111.85')
 Decimal('12510.4225')

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

Вы не должны использовать представление для удобочитаемой печати поплавков, вы должны использовать, например, str.format или какой-то другой метод представления.

Сохраняйте свои числа в качестве чисел для всех вычислений (независимо от того, делаете ли вы это с помощью чисел с плавающей запятой или десятичных дробей или чего-то еще...) и только округляйте или усекайте вещи при представлении.

Другие вопросы по тегам