Оператор сравнения Python не работает, если float (1) › float (1) оценивается как True, что мне не хватает?

Это не совсем с 1 > 1, но близко:

Я хочу сравнить две метки времени и сделать что-то, что if time > timestamp оценивается как True. Обе переменные имеют одинаковые float, как видно из pdb.

(Pdb) print time
1396836917.98
(Pdb) print last_timestamp
1396836917.98
(Pdb) if time > last_timestamp: print 'wtf'
wtf

Я ожидаю, что это будет оцениваться как False, похоже, это проблема float:

(Pdb) if float(time) > float(last_timestamp): print 'wtf'
wtf

int сравнение работает нормально

(Pdb) if int(time) > int(last_timestamp): print 'wtf'

Поэтому я ожидал проблемы с точностью доступных битов, представляющих число

(Pdb) if float(time)*100 > float(last_timestamp)*100: print 'wtf'
wtf

но он по-прежнему оценивается как True, если не осталось десятичных знаков..

Работа для меня прямо сейчас

if int(time*100) > int(last_timestamp*100): print 'wtf'

но мне бы очень хотелось понять, что происходит и как правильно использовать оператор > с float..


person gletscher    schedule 07.04.2014    source источник


Ответы (2)


Какую версию Python вы используете? print неявно вызывает str, который в старых версиях Python может скрывать различия между отдельными числами с плавающей запятой. Попробуйте вместо этого напечатать repr(time) и repr(last_timestamp). Если числа с плавающей запятой различны, repr создаст для них разные строки.

person Tim Peters    schedule 07.04.2014
comment
Python 2.7.5+ (default, Feb 27 2014, 19:37:08) [GCC 4.8.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. Я попробую repr(), но временные метки я собираю как string, так что разницы быть не должно.. - person gletscher; 07.04.2014
comment
Попробуйте repr. Неважно, откуда взялись временные метки. - person Tim Peters; 07.04.2014

Это звучит как проблема понимания с плавающей запятой.

В основном, за исключением некоторых редких чисел, числа с плавающей запятой не хранят числа точно, они хранят число, которое незначительно отличается от того, которое, как вы думаете, вы видите. Например (1-0,8 != 0,2).

Вот электронное письмо, которое я написал о Java, но практически все языки ведут себя одинаково:

Попробуйте вычислить (int)(4.1-0.1) в Java (и что-нибудь еще, используя стандартные алгоритмы IEE с плавающей запятой с усеченным целочисленным преобразованием), и вы получите результат 3.

Еще несколько примеров см.

http://ideone.com/ZseOnZ

Если вы преобразуете двойные числа в числа с плавающей запятой, вы получите совершенно другой набор значений, которые неверны, но, например, (int) (4.2f-0.2f) дает неправильный результат.

Для SQL вы можете проиллюстрировать то же самое:

        select CONVERT(INTEGER, CONVERT(float, 4.1)-CONVERT(float, 0.1))

Это дает результат 3.

person Tim B    schedule 07.04.2014