Python浮动到int转换


73

基本上,我将float转换为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。


浮点值不完全代表小数。这不是Python的事情。
Daniel Roseman


尽管其他人解释了为什么会发生这种情况,但我想展示我的解决方法,以使地板圆整并具有对浮点​​误差的一定容忍度nfloor = lambda x: round(x * 10**8) // 10**8
warownia1

Answers:


93
2.51 * 100 = 250.999999999997

int()函数仅将小数点后的数字截断,得到250。

int(round(2.51*100)) 

得到251作为整数。通常,浮点数不能准确表示。因此,应该注意舍入错误。如前所述,这不是特定于Python的问题。在所有计算机语言中,这都是一个反复出现的问题。


32

每个计算机科学家都应了解的浮点运算法则

浮点数不能代表所有数字。特别是,2.51不能用浮点数表示,而用非常接近它的数字表示:

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

如果使用int截断数字,则会得到:

250
401

看一下十进制类型。


4
按照“并非所有数字都可以用浮点数表示”的字眼,可以最精确地描述“浮点数不是100%准确的”(将数字文字转换为非常接近的浮点数,有时与数字相同)。实际上,所有浮点数都准确地表示了它们所代表的值。关键是它们并不代表所有可能的数字。
Eric O Lebigot 2011年

@EOL如果您允许,我可以对其进行编辑,也可以随时对其进行编辑。
雅各布

谢谢。我编辑了你的答案;随时根据自己的喜好调整我的散文。:)
Eric O Lebigot 2011年

1
了解二进制浮点数的重要一点(您可以从链接的文章中获得,但这里是TL; DR)是二进制点后的数字代表2的负幂:一半,四分之一,一因此,二进制浮点数只能精确地表示小数部分,这些小数部分是可用位表示的两个负幂之和。某些十进制表示形式有限的分数(例如0.1)需要二进制表示形式的位数无限,因此不能完全表示为float具有有限位数的。
kindall 2011年


7
>>> x = 2.51
>>> x*100
250.99999999999997

浮点数不正确。在这种情况下,它是250.99999999999999,实际上接近251,但是int()截断了小数部分,在这种情况下为250。

您应该看一下Decimal模块,或者如果需要在mpmath库http://code.google.com/p/mpmath/ :)进行大量计算,


3
int()不舍入到下面的整数,而是舍去小数部分。范例:int(-0.9) == 0
Eric O Lebigot

1

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库对接近整数的浮点数执行类似的操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.