当传入具有许多小数的浮点数时,内置的Python str()函数会输出一些奇怪的结果。这就是:
>>> str(19.9999999999999999)
>>> '20.0'
我期待得到:
>>> '19.9999999999999999'
有谁知道为什么?也许可以解决它?
谢谢!
答案 0 :(得分:8)
这不是str()
轮次,而是你首先使用花车的事实。浮动类型很快,但精度有限;换句话说,他们设计不精确。这适用于所有编程语言。有关浮动怪癖的更多详情,请阅读“What Every Programmer Should Know About Floating-Point Arithmetic”
如果您想存储并使用精确数字操作,请使用decimal
模块:
>>> from decimal import Decimal
>>> str(Decimal('19.9999999999999999'))
'19.9999999999999999'
答案 1 :(得分:6)
浮点数为32位(至少为C)。其中一个位分配给符号,一些分配给尾数,一些分配给指数。您不能将每个十进制数组合成无限数量的数字到32位。因此,浮点数很大程度上取决于舍入。
如果你试试str(19.998)
,它可能会给你一些至少接近19.998的东西,因为32位有足够的精度来估计它,但像19.999999999999999这样的东西太精确了,无法估计32位,所以它转向最接近的可能值,恰好是20。
答案 2 :(得分:3)
请注意,这是了解浮点(固定长度)数字的问题。大多数语言与Python的确完全(或非常相似)。
Python float
是IEEE 754 64位二进制浮点。它限制在53位精度,即略小于16位精度的十进制数字。 19.9999999999999999
包含18位小数;它不能完全表示为float
。 float("19.9999999999999999")
生成最近的浮点值,该值恰好与float("20.0")
相同。
>>> float("19.9999999999999999") == float("20.0")
True
如果“小数点后”表示“小数点后的多位数字”,请注意在小数点之前有多个小数位时会发生相同的“奇怪”结果:< / p>
如果你想要完整的 更新有趣的是 是的, 您可以更改限制,但它仍然是限制精度。您仍然需要知道数字格式的特征,以便在没有“惊人”结果的情况下有效地使用它,并且通过较慢的操作来购买额外的精度(除非您使用第三方>>> float("199999999999999999")
2e+17
float
精度,不要使用str(),请使用repr():>>> x = 1. / 3.
>>> str(x)
'0.333333333333'
>>> str(x).count('3')
12
>>> repr(x)
'0.3333333333333333'
>>> repr(x).count('3')
16
>>>
decimal
经常被规定为治愈浮游引起的惊讶的全部治疗方法。这通常伴随着0.1 + 0.1 + 0.1 != 0.3
这样的简单示例。没有人停下来指出decimal
有其缺点,例如。>>> (1.0 / 3.0) * 3.0
1.0
>>> (Decimal('1.0') / Decimal('3.0')) * Decimal('3.0')
Decimal('0.9999999999999999999999999999')
>>>
float
限制为53个精度的二进制数字。默认情况下,decimal
限制为28位精度的十进制数字。>>> Decimal(2) / Decimal(3)
Decimal('0.6666666666666666666666666667')
>>>
cdecimal
模块)。
答案 3 :(得分:1)
对于任何给定的二进制浮点数,有一组无限的小数部分,在输入时,舍入到该数字。 Python的str
从这个集合产生最短小数部分会遇到麻烦;有关通用算法,请参阅GLS的论文http://kurtstephens.com/files/p372-steele.pdf(IIRC,他们使用了一种在大多数情况下避免任意精度数学的细化)。您碰巧输入了一个小数部分,该小数部分舍入为浮点数(IEEE double),其最小可能小数与您输入的小数位数不同。