Странность Python с плавающей запятой

Сегодня вечером увидел неожиданное поведение Python. Почему следующая распечатка «не равна»?!

num = 1.00
num -= .95
nickel = .05

if nickel != num:
    print 'not equal'
else:
    print 'equal' 

person Benjamin Powers    schedule 12.05.2012    source источник
comment
docs.python.org/tutorial/floatingpoint.html   -  person jamylak    schedule 12.05.2012
comment
Отличные вещи, ребята. Был вокруг некоторое время и никогда не сталкивался с этим. Спасибо.   -  person Benjamin Powers    schedule 12.05.2012


Ответы (3)


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

>>> num = 1.00
>>> num
1.0
>>> num -= 0.95
>>> num
0.050000000000000044
>>> nickel = .05
>>> nickel
0.05
person voithos    schedule 12.05.2012

Вам может пригодиться модуль decimal.

>>> TWOPLACES = Decimal(10) ** -2
>>> Decimal(1).quantize(TWOPLACES)-Decimal(0.95).quantize(TWOPLACES) == Decimal(0.05).quantize(TWOPLACES)
True

Или, альтернативно:

import decimal
decimal.getcontext().prec = 2
decimal.Decimal(1.00) - decimal.Decimal(0.95)

Из того, что вы назвали переменной nickel, я сделал вывод, что вы думали о деньгах. Очевидно, что для этого не подходит тип с плавающей запятой.

person jgritty    schedule 12.05.2012
comment
Не соглашусь, та же проблема. >>> Decimal(.05) == Decimal(1.00 - .95) >>> False - person jb.; 12.05.2012
comment
@jb. Это та же проблема, потому что вы преобразовали результат операции с плавающей запятой в десятичное число. Вам нужно выполнить операцию над десятичными дробями. Вы также должны быть осторожны при назначении десятичных знаков из поплавков. Обратите внимание на разницу между Decimal(0.1) и Decimal('0.1') - person Paul S; 14.05.2012

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

person jb.    schedule 12.05.2012