Ошибка округления Python с номерами с плавающей запятой

Я не знаю, является ли это очевидной ошибкой, но при запуске скрипта Python для изменения параметров моделирования я понял, что результаты с delta = 0,29 и delta = 0,58 отсутствовали. В ходе расследования я заметил, что следующий код Python:

for i_delta in range(0, 101, 1): delta = float(i_delta) / 100 (...) filename = 'foo' + str(int(delta * 100)) + '.dat' 

сгенерированные идентичные файлы для delta = 0,28 и 0,29, то же самое с 0,57 и 0,58, причина в том, что python возвращает float (29) / 100 как 0.28999999999999998. Но это не систематическая ошибка, а не то, что происходит с каждым целым числом. Поэтому я создал следующий скрипт Python:

 import sys n = int(sys.argv[1]) for i in range(0, n + 1): a = int(100 * (float(i) / 100)) if i != a: print i, a 

И я не вижу никакой картины в числах, для которых эта ошибка округления происходит. Почему это происходит с этими конкретными цифрами?

2 Solutions collect form web for “Ошибка округления Python с номерами с плавающей запятой”

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

Читайте, что каждый компьютерный ученый должен знать о арифметике с плавающей точкой .

Его очень хорошо известно из-за характера чисел с плавающей запятой .

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

Например,

 >>> from decimal import Decimal >>> Decimal(29)/Decimal(100) Decimal('0.29') >>> Decimal('0.29')*100 Decimal('29') >>> int(Decimal('29')) 29 

В общем случае десятичное число, вероятно, выходит за борт и все еще будет иметь ошибки округления в редких случаях, когда число не имеет конечного десятичного представления (например, любая дробь, где знаменатель не равен 1 или делится на 2 или 5 – факторы десятичной базы (10)). Например:

 >>> s = Decimal(7) >>> Decimal(1)/s/s/s/s/s/s/s*s*s*s*s*s*s*s Decimal('0.9999999999999999999999999996') >>> int(Decimal('0.9999999999999999999999999996')) 0 

Поэтому лучше всего всегда округлять до того, как вы будете плавать с плавающей точкой в ​​ints, если вы не хотите использовать функцию напольного покрытия.

 >>> int(1.9999) 1 >>> int(round(1.999)) 2 

Другой альтернативой является использование класса фракций из библиотеки фракций, которая не приближается. (Он просто продолжает добавлять / вычитать и умножать численные числители и знаменатели по мере необходимости).

  • numpy.savetxt "tuple index out the range"?
  • Python: печать списков сбоку
  • Преобразование десятичного в двоичный файл в python
  • glpk err, import glpk module не найден
  • Ограничения на .format в python
  • Как сделать несколько аргументов для функции map, где один остается в python?
  • Использование python для фильтрации файлов на диске
  • Как переопределить stderr out и stdout на отдельные журналы?
  • Python - лучший язык программирования в мире.