簡體   English   中英

為什么str()圍繞浮動?

[英]Why does str() round up floats?

當傳入具有許多小數的浮點數時,內置的Python str()函數會輸出一些奇怪的結果。 這是發生的事情:

>>> str(19.9999999999999999)
>>> '20.0'

我期待得到:

>>> '19.9999999999999999'

有誰知道為什么? 也許可以解決它?

謝謝!

這不是str() ,而是你首先使用花車的事實。 浮動類型很快,但精度有限; 換句話說,它們在設計上不精確的 這適用於所有編程語言。 有關浮動怪癖的更多詳細信息,請閱讀“ 每個程序員應該知道的關於浮點算術的內容

如果要存儲和操作精確數字,請使用decimal模塊:

>>> from decimal import Decimal
>>> str(Decimal('19.9999999999999999'))
'19.9999999999999999'

浮點數為32位(至少為C)。 其中一個位分配給符號,一些分配給尾數,一些分配給指數。 您不能將每個十進制數組合成無限數量的數字到32位。 因此,浮點數很大程度上取決於舍入。

如果你嘗試str(19.998) ,它可能會給你一些至少接近19.998的東西,因為32位具有足夠的精度來估計它,但像19.999999999999999這樣的東西太精確而不能用32位估計,所以它舍入到最接近的可能值,恰好是20歲。

請注意,這是了解浮點(固定長度)數字的問題。 大多數語言與Python的確完全(或非常相似)。

Python floatIEEE 754 64位二進制浮點數。 它僅限於53位精度,即略低於16位精度的十進制數字。 19.9999999999999999包含18位小數; 它不能完全表示為float float("19.9999999999999999")生成最近的浮點值,該值恰好與float("20.0")

>>> float("19.9999999999999999") == float("20.0")
True

如果用“多個小數”表示“小數點后的多位數”,請注意當小數點有多個十進制數字時,會發生相同的“奇怪”結果:

>>> 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模塊)。

對於任何給定的二進制浮點數,有一組無限的小數部分,在輸入時,舍入到該數字。 Python的str從這個集合產生最短的小數部分會遇到一些麻煩; 有關通用算法,請參閱GLS的論文http://kurtstephens.com/files/p372-steele.pdf(IIRC他們使用一種在大多數情況下避免任意精度數學的細化)。 您碰巧輸入了一個小數部分,該小數部分舍入為浮點數(IEEE double),其最小可能小數與您輸入的小數位數不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM