Python float 到 int 的转换

Posted

技术标签:

【中文标题】Python float 到 int 的转换【英文标题】:Python float to int conversion 【发布时间】:2011-09-28 00:16:41 【问题描述】:

基本上,我将浮点数转换为整数,但我并不总是有预期值。

这是我正在执行的代码:

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 的事情。 Python rounding error with float numbers 的可能重复项 虽然其他人解释了为什么会发生这种情况,但我想展示我的解决方法来获得对浮点错误有一定容忍度的地板舍入 nfloor = lambda x: round(x * 10**8) // 10**8 【参考方案1】:

使用二进制浮点表示的语言(Python 就是其中之一)不能准确地表示所有小数值。如果您的计算结果是 250.99999999999(也可能是),那么取整数部分将得到 250。

有关此主题的规范文章是What Every Computer Scientist Should Know About Floating-Point Arithmetic。

【讨论】:

【参考方案2】:
>>> x = 2.51
>>> x*100
250.99999999999997

浮点数不准确。在本例中为 250.99999999999999,确实接近 251,但 int() 将小数部分截断,在本例中为 250。

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

【讨论】:

int() 不会四舍五入到下面的整数,而是截断小数部分。示例:int(-0.9) == 0.【参考方案3】:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

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

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

250
401

看看Decimal 类型。

【讨论】:

“浮点数不是 100% 准确”将沿着“并非所有数字都可以用浮点数表示”这一行进行最准确的描述(数字文字转换为浮点数-点数非常接近,有时与数字相同)。事实上,所有浮点数都准确地代表了它们所代表的值。关键是它们并不代表所有可能的数字。 @EOL 如果您允许,我可以编辑它或随意编辑它。 谢谢。我编辑了你的答案;随意调整我的散文以适应您的口味。 :) 关于二进制浮点数的重要知识(您可以从链接的文章中获得,但这里有一个 TL;DR)是二进制点之后的数字表示二的负幂:一一半、四分之一、八分之一等。因此,二进制浮点数只能精确地表示由可用位表示的 2 的负幂之和的分数。某些在十进制表示法中有限的分数(例如 0.1)需要在二进制表示法中无限位数,因此不能在具有有限位数的float 中完全表示。跨度> 【参考方案4】:
2.51 * 100 = 250.999999999997

int() 函数只是截断小数点处的数字,得到 250。使用

int(round(2.51*100)) 

获取 251 作为整数。一般来说,浮点数不能精确表示。因此,应注意舍入误差。如前所述,这不是 Python 特有的问题。这是所有计算机语言中反复出现的问题。

【讨论】:

【参考方案5】:

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 库对接近整数的浮点数做了类似的事情。

【讨论】:

以上是关于Python float 到 int 的转换的主要内容,如果未能解决你的问题,请参考以下文章

python中怎么把string转换成int

Python,确定字符串是否应转换为Int或Float

使用python中的所有值将数据帧float转换为int

在 Python 3 中将字符串转换为 int 或 float?

Python浮动到int转换

python 中将str类型转化为int