簡體   English   中英

Python乘法失去浮點精度

[英]Python multiplication losing floating point precision

我最近在處理浮點數,我意識到浮點數出乎我的意料。 這是一個例子

a = 0.1
print(f"{a:0.20f}")
#'0.10000000000000000555'
b = a * 10
print(f"{b:0.20f}")
#'1.00000000000000000000'

我希望最后一次打印輸出1.00000000000000005551 (即 1 后跟數字 1 到 21 of 0.1 )。

我很好奇的是為什么當乘以 10 時浮點誤差會消失。算術的正常規則表明浮點誤差會被傳播,但這實際上並沒有發生。 為什么會發生這種情況? 有沒有辦法避免它?

的10和0.1000000000000000055511151231257827021181583404541015625確切實數算術乘積,0.1 IEEE 754的64位二進制表示,是1.000000000000000055511151231257827021181583404541015625。

它不能完全代表。 它由 1.0 和 1.00000000000000022204460492503130808472633336181640625 括起來

它更接近 1.0,因此這是乘法的舍入到最接近的結果。

我使用一個簡短的 Java 程序計算了這些數字:

import java.math.BigDecimal;

public strictfp class Test {
    public static void main(String[] args) {
        BigDecimal rawTenth = new BigDecimal(0.1);
        BigDecimal realProduct = rawTenth.multiply(BigDecimal.TEN);
        System.out.println(realProduct);
        System.out.println(new BigDecimal(Math.nextUp(1.0)));
    }
}

輸出:

1.0000000000000000555111512312578270211815834045410156250
1.0000000000000002220446049250313080847263336181640625

這個答案顯示了如何確定將 1/10 轉換為浮點數並乘以 10 只需使用一點算術即可得出正好為 1; 無需計算大量或精確的數字。

您的 Python 實現使用常見的 IEEE-754 binary64 格式。 (Python 對應該使用哪種浮點格式的實現並不嚴格。)在這種格式中,數字實際上表示為應用於某個 53 位整數乘以某個 2 的冪的符號(+ 或 -)。 因為 2 -4 ≤ 1/10 < 2 -3 ,最接近 1/10 的可表示數是某個整數 M 乘以 2 -3-53 (-53 將 53 位整數縮放到 ½ 和 1 之間,而 -3 將其縮放到 2 -4和 2 -3 之間。)讓我們稱其為可表示數 x。

然后我們有 x = M•2 −56 = 1/10 + e,其中 e 是當我們將 1/10 舍入到最接近的可表示值時發生的一些舍入誤差。 由於我們四舍五入到最接近的可表示值,|e| ≤ ½•2 −56 = 2 −57

要准確找出 e 是什么,請將 1/10 乘以 2 56 WolframAlpha告訴我們它是 7205759403792793+3/5。 為了獲得最接近的可表示值,我們應該向上取整,因此 M = 7205759403792794 和 e = 2/5 • 2 −56 雖然我用 WolframAlpha 來說明這一點,但我們不需要 M,我們可以通過觀察兩個模 10 的冪的模式找到 e:2 1 →2, 2 2 →4, 2 3 →8, 2 4 →6, 2 5 →2, 2 6 →4,所以模式以4為循環重復,56模4為0,所以2 56模10與2 4 , 6有相同的余數,所以分數是6/10 = 3/5。 我們知道應該四舍五入到最接近的整數 1,所以 e = 2/5 • 2 −56

所以 x = M•2 −56 = 1/10 + 2/5•2 −56

現在我們可以計算出用浮點算法計算 10•x 的結果。 結果就像我們首先用實數算術計算 10•x 然后四舍五入到最接近的可表示值。 在實數算術中,10•x = 10•(1/10 + 2/5•2 −56 ) = 1 + 10•2/5•2 −56 = 1 + 4•2 −56 = 1 + 2 − 54 . 兩個相鄰的可表示值是 1 和 1 + 2 -52 ,並且 1 + 2 -54比 1 + 2 -52更接近於 1。 所以結果是1。

暫無
暫無

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

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