Python浮点数转整数

77

我要把一个浮点数转换成整数,但我得到的值有时候不是我期望的。

这是我执行的代码:

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.50->5.00范围内,只有2.51和4.02是导致这种奇怪行为的值。当给定相同操作时,该范围内的其他两位数字值都可以无问题地转换为整数。

那么,我错过了什么导致了这些结果呢?顺便说一下,我正在使用Python 2.7.2。


浮点数值不能精确地表示小数。这不是Python的问题。 - Daniel Roseman
可能是 Python 浮点数四舍五入误差 的重复问题。 - mac
虽然其他人已经解释了为什么会发生这种情况,但我想展示一下我的解决方法,以获得带有一定浮点误差容差的向下取整结果:nfloor = lambda x: round(x * 10**8) // 10**8 - warownia1
6个回答

97
2.51 * 100 = 250.999999999997

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

int(round(2.51*100)) 

要将251作为整数获取。一般来说,浮点数无法精确表示。因此,应该注意舍入误差。正如提到的那样,这不是Python特定的问题。这是所有计算机语言中经常出现的问题。


35

每个计算机科学家都应该知道的浮点数算术知识

浮点数无法表示所有数字。特别是,2.51不能被浮点数表示,而是由非常接近它的一个数字表示:

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

如果使用int,它会截断数字,你将得到:

250
401

看一下Decimal类型。


4
“浮点数不是百分之百准确的” 可以更加准确地描述为:“并非所有的数字都可以用浮点数来表示”(数字字面量会被转换成一个非常接近,有时甚至与该数字相同的浮点数)。实际上,所有的浮点数都能够准确地代表它们所表示的值。关键点在于,它们不能代表所有可能的数字。 - Eric O. Lebigot
如果您允许,我可以编辑它,或者您也可以自行编辑。 - Jacob
谢谢。我编辑了你的回答,你可以随意按照自己的口味进行调整。:) - Eric O. Lebigot
1
关于二进制浮点数的重要知识(您可以从链接的文章中了解到,但这里有一个TL;DR),需要知道的是,在二进制点后的数字表示二的负次幂:一半、四分之一、八分之一等。因此,二进制浮点数只能准确地表示可用位表示的负二次幂之和的分数。某些在十进制表示法中是有限的分数(例如0.1)在二进制表示法中需要无限数量的位,因此不能完全表示为具有有限位数的float - kindall

12

使用二进制浮点数表示的语言(如Python)不能精确表示所有分数值。如果您的计算结果是250.99999999999(可能会出现这种情况),那么取整数部分将得到250。

关于此主题的一篇经典文章是《计算机科学家应该了解的浮点运算知识》


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 库对于接近整数的浮点数也会进行类似的处理。

0
要将其转换为整数,您应该使用int()函数:
def myFunction(x, y):
    return int(x / y)

然而,如果 x / y 是类似 2.8 这样的数,int() 将删除小数并将其转换为 2。因此,在使用 int() 之前,应该使用 round() 函数,它看起来像这样:
def myFunction(x, y):
    return int(round(x / y))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接