Изменение порядка чисел в простой математической операции дает другой результат?

#python #python-3.x

Вопрос:

 print((1199/1070)*1070)
 

возвращает: 1198.9999999999998

 print((1070/1070)*1199)
 

возвращает 1199.0

как преодолеть такое поведение ? ( Версия Python == 3.8.3 )

Комментарии:

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

2. как сказал @buran, это результат арифметики с плавающей запятой, и вы можете прочитать об этом подробнее в docs.python.org/3/tutorial/floatingpoint.html . Если числа малы, вы обычно можете преодолеть это, сначала умножив, а затем разделив, но это действительно зависит от ситуации.

3. @NuLo на самом деле я не могу изменить порядок. мне нужно сначала вычислить соотношение, а затем умножить его на число. это число и соотношение происходят из разных функций.

Ответ №1:

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

Чтобы исправить это, вы можете использовать встроенную fractions библиотеку: https://docs.python.org/3/library/fractions.html

 from fractions import Fraction

print(float(Fraction(1199)/1070*1070)) # prints: 1199.0
print(float(Fraction(1070)/1070*1199)) # prints: 1199.0
 

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

Комментарии:

1. Спасибо , но разве это не должно быть похоже на : печать(плавающая(дробь(1199,1070)*1070))

2. @SaeidMohammadiNejati они эквивалентны, дробь переопределяет операторы. Вы используете объект дроби до тех пор, пока преобразование не будет выполнено с плавающей точкой, что приведет к снижению производительности.