python中奇怪的浮点数到整数转换问题

Posted

技术标签:

【中文标题】python中奇怪的浮点数到整数转换问题【英文标题】:Weird float to integer conversion issue in python 【发布时间】:2021-01-03 15:22:03 【问题描述】:

对于我编写的涉及有限代数域的程序计算,我需要检查(2**58-1)/61 是否为整数。然而python似乎表明它是,虽然它是not。

例如-

>>> (2**58-1)/61
4725088133634619.0

即使在使用 numpy 函数时也会出现此问题 -

>>> np.divide(np.float64(2**58)-1,np.float64(61))
4725088133634619.0

虽然 python 确实正确计算了 2**58,但还是会发生这种情况(我认为这个问题很普遍,但我使用这些数字遇到了它)。

【问题讨论】:

【参考方案1】:

如果您使用普通的/ 除法,您的结果是一个浮点数,具有相关的有限精度。结果被四舍五入,在你的情况下,它被四舍五入为 4725088133634619.0 - 但这并不能证明它是一个整数。

如果要检查除以61的结果是否为整数,请使用模运算符测试除以61的余数是否为0:

>>> (2**58-1) % 61
45

如您所见,事实并非如此。

【讨论】:

谢谢!但是怎么用np.float64的时候还是四舍五入呢? @proton:这个数字正好适合浮点精度下降到个位数。 .0 是多余的,只是为了表明它的类型是 float【参考方案2】:

至于@Thierry Lathuille 提到的浮点有限精度,Python 的float 使用64 位并且是双精度,为尾数提供53 位(np.float64 也是如此)。这意味着并非所有数字> 2**53 都可以使用float 表示,我们会​​损失精度。例如,2**53 == 2**53 + 1 在双精度下为真。更详细的在这里:

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

Is floating point math broken?

【讨论】:

【参考方案3】:

已经给出了正确的答案。我只是添加另一种方法(与已经说过的没有太大区别)。

由于表示错误的固有限制,您可能想要做的是对 python 使用 divmod(),对 numpy 使用 numpy.divmod()。这样您就可以检查商和余数。

print(divmod((2**58-1),61))

给出商和余数

(4725088133634618, 45)

在 numpy 中,您可能希望使用类似的 divmod 函数,但数字应该是 np.int 类型而不是 np.float 类型(由于上述表示错误)。

np.divmod(np.int64(2**58)-1,np.int8(61))

上面给出了商和余数。

(4725088133634618, 45)

【讨论】:

以上是关于python中奇怪的浮点数到整数转换问题的主要内容,如果未能解决你的问题,请参考以下文章

当数字在 0 和 1 之间时显示没有整数部分的浮点数

将范围-1到1的浮点数转换为短的快速方法?

Question20180128 十进制转换成二进制浮点数

如何将列表中的字符串值更改为 Python 中的浮点数

c语言中如何将10进制的浮点数转化为16进制数

Python3 大浮点数的停止除法