Преобразование Python в int - PullRequest
61 голосов
/ 04 июля 2011

Обычно я конвертирую число с плавающей точкой в ​​int, но у меня не всегда есть ожидаемое значение.

Вот код, который я выполняю:

x = 2.51

print("--------- 251.0")
y = 251.0
print(y)
print(int(y))

print("--------- 2.51 * 100")
y = x * 100
print(y)
print(int(y))

print("--------- 2.51 * 1000 / 10")
y = x * 1000 / 10
print(y)
print(int(y))

print("--------- 2.51 * 100 * 10 / 10")
y = x * 100 * 10 / 10
print(y)
print(int(y))

x = 4.02
print("--------- 402.0")
y = 402.0
print(y)
print(int(y))

print("--------- 4.02 * 100")
y = x * 100
print(y)
print(int(y))

print("--------- 4.02 * 1000 / 10")
y = x * 1000 / 10
print(y)
print(int(y))

print("--------- 4.02 * 100 * 10 / 10")
y = x * 100 * 10 / 10
print(y)
print(int(y))

И вот результат (первое значение - результат операции, второе значение - int () той же операции):

--------- 251.0
251.0
251
--------- 2.51 * 100
251.0
250
--------- 2.51 * 1000 / 10
251.0
251
--------- 2.51 * 100 * 10 / 10
251.0
250
--------- 402.0
402.0
402
--------- 4.02 * 100
402.0
401
--------- 4.02 * 1000 / 10
402.0
401
--------- 4.02 * 100 * 10 / 10
402.0
401

2,51 и 4,02 - единственные значенияэто приводит к странному поведению в диапазоне 2,50 -> 5,00.Каждые две другие цифры в этом диапазоне без проблем преобразуются в int при выполнении тех же операций.

Итак, что же мне не хватает, что приводит к этим результатам?Кстати, я использую Python 2.7.2.

Ответы [ 5 ]

78 голосов
/ 04 июля 2011
2.51 * 100 = 250.999999999997

Функция int() просто усекает число в десятичной точке, давая 250. Используйте

int(round(2.51*100)) 

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

32 голосов
/ 04 июля 2011

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

Числа с плавающей запятой не могут представлять все числа. В частности, 2.51 не может быть представлен числом с плавающей запятой, и представлен числом, очень близким к нему:

>>> print "%.16f" % 2.51
2.5099999999999998
>>> 2.51*100
250.99999999999997
>>> 4.02*100
401.99999999999994

Если вы используете int, который усекает числа, вы получите:

250
401

Посмотрите на тип Десятичный .

10 голосов
/ 04 июля 2011

Языки, которые используют двоичные представления с плавающей запятой (Python - один), не могут точно представлять все дробные значения.Если результат ваших вычислений равен 250,999999999999 (и это может быть), то если принять целочисленную часть, получится 250.

Каноническая статья на эту тему: Что должен знать каждый учёный-компьютерщик о плавающемТочка Арифметика .

7 голосов
/ 04 июля 2011
>>> x = 2.51
>>> x*100
250.99999999999997

числа с плавающей точкой неточны.в данном случае это 250.99999999999999, что на самом деле близко к 251, но int () усекает десятичную часть, в данном случае 250.

вам следует взглянуть на десятичный модуль или, возможно, вам придетсямного вычислений в библиотеке mpmath http://code.google.com/p/mpmath/:),

1 голос
/ 13 октября 2018

int преобразуется усечением, как уже упоминалось другими. Это может привести к тому, что ответ будет отличаться от ожидаемого. Одним из способов решения этой проблемы является проверка того, является ли результат «достаточно близким» к целому числу и, соответственно, корректировка, в противном случае - обычное преобразование. Это при условии, что вы не получите слишком много округления и ошибки расчета, что является отдельной проблемой. Например:

def toint(f):
    trunc = int(f)
    diff = f - trunc

    # trunc is one too low
    if abs(f - trunc - 1) < 0.00001:
        return trunc + 1
    # trunc is one too high
    if abs(f - trunc + 1) < 0.00001:
        return trunc - 1
    # trunc is the right value
    return trunc

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

...