在Python中将浮点数转换为整数类型,适用于大整数/数字。

3
需要在我正在处理的下面这段代码上寻求一些帮助。为什么当它经过类型转换时,"a"中的原始数字与"c"中的不同?有没有办法让它们在经过浮点数到整数类型转换时保持一致?
a = '46700000000987654321'
b = float(a)  => 4.670000000098765e+19
c = int(b)    => 46700000000987652096
a == c        => False

你需要思考一下为什么要这样做。如果你需要进行算术运算,或许应该将其保留为整数。下面建议的 Decimal 类型比整数运算或浮点数运算要慢得多。另一方面,实际情况中需要保留超过16位精度的情况非常非常罕见。 - Tim Roberts
2个回答

3
修改后的我对另一个问题的回答(合理地)重复到这个问题:

这是因为46700000000987654321大于C double的整数表示限制(Python float的实现方式)。

通常情况下,C语言中的双精度浮点数(double)采用IEEE 754标准,使用64位二进制浮点数表示,其中53位用于整数精度(最后一个连续的整数值是2 ** 53 - 1,接着是2 ** 53;它不能表示2 ** 53 + 1)。问题在于,46700000000987654321需要66位整数精度来存储((46700000000987654321).bit_length()可以提供这个信息)。当一个值过大以至于超出了有效数字(即整数部分),浮点数的指数部分就会被用来按2的幂次方缩放较小的整数值,使其大致处于原始值的范围内。但这也意味着可表示的整数开始跳过,首先是每增加一位就跳过2(当需要超过53位时),然后是每增加一位就跳过4(当需要超过54位时),然后是每增加一位就跳过8(当需要超过55位时),然后是每增加一位就跳过16(当需要超过56位时),以此类推,每增加一位,可表示的值之间的距离就会加倍。
在您的情况下,将46700000000987654321转换为float后,其整数值为46700000000987652096(如您所指出),低位数字失去了精度。
如果您需要任意精度的十进制浮点数运算,请使用decimal.Decimal替换float的使用(方便的是,您的初始值已经是一个字符串,因此您不会在输入float和实际存储值之间失去精度);默认精度可以处理这些值,如果您需要更大的值,可以增加精度。如果您这样做(并将a转换为int进行比较,因为str永远不等于任何数字类型),则可以得到您期望的行为:
from decimal import Decimal as Dec, getcontext

a = "46700000000987654321"
b = Dec(a); print(b)  # => 46700000000987654321
c = int(b); print(c)  # => 46700000000987654321
print(int(a) == c)    # => True

在线尝试!

如果你在交互式解释器中回显Decimal而不是使用print,你会看到Decimal('46700000000987654321'),这是Decimalrepr形式,但它的数值是46700000000987654321。如果将其转换为int,或通过任何不使用repr的方法进行字符串化,例如print,它将显示为46700000000987654321

1
请阅读关于浮点算术的问题和限制的文件:Floating Point Arithmetic: Issues and Limitationshttps://docs.python.org/3/tutorial/floatingpoint.html 以您的示例为例:
from decimal import Decimal
a='46700000000987654321'

b=Decimal(a)

print(b)    #46700000000987654321

c=int(b)

print(c)    #46700000000987654321

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