簡體   English   中英

Python的while循環條件中的浮點數演算和錯誤

[英]Calculus of Floating-point numbers and error in a while loop condition in Python

我嘗試在Python中做一個簡單的循環。 如果d <= 4,則循環應該停止。不幸的是,由於浮點算法問題,最后一次演算給出了4.000000000000001(而不是4),然后停止了循環。 有沒有針對這種問題的簡單解決方案?

輸入

import matplotlib.pyplot as plt
import numpy as np

A = 4
B = 2
C = 0.1

d = 0
while d <= A: 
    d += B*C
    print(d)

產量

0.2
0.4
0.6000000000000001
0.8
1.0
1.2
1.4
1.5999999999999999
1.7999999999999998
1.9999999999999998
2.1999999999999997
2.4
2.6
2.8000000000000003
3.0000000000000004
3.2000000000000006
3.400000000000001
3.600000000000001
3.800000000000001
4.000000000000001

打印與浮點數學無關。

你的循環

  1. 測試d <= 4
    1. 計算新的d
    2. 打印d具有任何值
 d = 0 while d <= A: # here d <= 4 d += B*C # here is is recomputed and now bigger 4 print(d) # here it gets printed 

您需要在使用當前值進行打印之前進行測試-或先打印,然后重新計算:

A = 4
B = 2
C = 0.1

d = 0
while True: 
    d += B*C
    if d > A:
        break
    print(d)

為避免舍入誤差累積,請將計算結果更改為非增量形式:

A = 4
B = 2
C = 0.1

d=0
rounds = 0
while d < A:
    rounds += 1
    d = B*C*rounds  # do not accumulate errors: kinda hackish though
    print(d)

輸出:

0.2
0.4
0.6000000000000001
0.8
1.0
1.2000000000000002
1.4000000000000001
1.6
1.8
2.0
2.2
2.4000000000000004
2.6
2.8000000000000003
3.0
3.2
3.4000000000000004
3.6
3.8000000000000003
4.0

由於d在最后一次迭代中大於(略大於)4,因此d在下一次迭代中不會進入循環,因此不會打印4.200(我猜是您所期望的)。 要解決此問題(這類問題),可以在進行比較時使用此結構。 只需根據您需要的精度選擇epsilon。

import matplotlib.pyplot as plt
import numpy as np

A = 4
B = 2
C = 0.1
epsilon = 0.001
d = 0
while d <= A + epsilon: 
    d += B*C
    print(d)

在下面的鏈接中,可以找到更多精致,通用和優美的版本來解決此問題。 https://www.learncpp.com/cpp-tutorial/35-relational-operators-comparisons/

請注意,這與Python本身無關。 任何使用IEEE 754編碼或任何類似的二進制編碼表示浮點值的語言(例如C)都會遇到這個問題。 那是因為像0.2這樣的十進制值不能像IEEE 754這樣的二進制格式精確地表示。如果您用谷歌“比較浮點值”,您會發現很多描述此問題以及如何處理它的論文。 例如, 這個

根據您的情況,使用比例縮放整數表示可能更好。 例如,如果您的值始終具有1/10的精度,則只需按10縮放:11為1.1,38為3.8,依此類推。還有decimal模塊。

暫無
暫無

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

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