2016-09-04 91 views
0

在我的現實生活中,我將一個窗口小部件的大小乘以size_hint,它可以是從0.1.之間的任意值。假設小部件的最小尺寸是0,最大尺寸是10,000,我應該在哪個數字上出現錯誤,當我乘以size * size_hint確定一個浮點數有多少個十進制數是精確的

例如*上0.1上..

>>> from decimal import Decimal 
>>> Decimal.from_float(.1) 
Decimal('0.1000000000000000055511151231257827021181583404541015625') 
#       ^
#       |_ here 

..第十八十進制數字發生錯誤。

在另一方面,下面的錯誤在14日小數出現

>>> 1001*.2 
200.20000000000002 

問題

  • 有沒有一種方法,以確定在哪個確切十進制數會出現錯誤?
  • Python 2和Python 3有區別嗎?

使用小數點而不是浮點數不是一個選項,並且sizesize_hint都由用戶提供。


* 我曾經因爲>>> 0.1Fraction顯示爲..在控制檯0.1,但我認爲這是關係到它的打印方式,而不是它是如何存儲。

+0

第十五位是保證正確任何單一的十進制數的最後一個。但是,這些錯誤會累積下來。然而,如果你的數字是2的負冪,它可以更精確... –

+0

@AnttiHaapala你確定嗎?在'1001 * .2'的情況下,最後一個正確的數字是第13位。此外,'size_hint'由用戶提供,因此2的冪不是一個選項。 –

+0

@Fermiparadox最後一位數字「2」是* 17th *有效數字。 –

回答

0

我建議你把讀來pep485

使用==符來比較浮點值是不走正道,而不是考慮使用math.isclosecmath.isclose,這裏是使用你的價值觀一個小例子:

try: 
    from math import isclose 

    v1 = 101 * 1/5 
    v2 = 101 * (1/5) 
except: 
    v1 = float(101) * float(1)/float(5) 
    v2 = float(101) * (float(1)/float(5)) 

    def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): 
     return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) 

print("v1==v2 {0}".format(v1 == v2)) 
print("isclose(v1,v2) {0}".format(isclose(v1, v2))) 

正如你所看到的,我明確地鑄造漂浮在蟒蛇2.x的和使用文檔中提供的功能,與蟒蛇3.x我只是直接使用你的數值和數學模塊提供的功能。

+0

恐怕這並不能回答我的任何一個問題。提供頂部的示例僅僅是爲了展示我遇到的問題,但如果它令人困惑,我可以將其刪除。 –

+0

@Fermiparadox你找到的問題是因爲你沒有比較正確的浮點值,因爲我已經提到不使用'=='運算符。關於你的問題1)你可以比較浮點值的字符串表示來知道確切的數字(不推薦和緩慢),沒有人這樣做,並且2)閱讀[this](https://docs.python.org/ 3/tutorial/floatingpoint.html) – BPL

+0

@Fermiparadox另外,我建議你讀一讀[this](http://gamedevs.org/uploads/numerical-robustness-geometric-calculations.pdf),它不是'蟒蛇相關雖然 – BPL

2

如果我們假設小部件的大小正好存儲,那麼有2個錯誤來源:size_hint從小數點 - >二進制數的轉換以及乘法。在Python中,這些都應該正確舍入到最近,所以每個應該有一半ulp的相對誤差(unit in the last place)。由於第二個操作是乘法,所以我們可以添加邊界以獲得總的相對誤差,其將被限制爲1 ulp或2 -53

轉換爲十進制:

>>> math.trunc(math.log10(2.0**-53)) 
-15 

這意味着你應該精確到15個顯著數字。

不應該有Python 2和3之間的任何差別:Python中早已相當嚴格的有關浮點行爲,我所知道的唯一的變化是round函數的行爲,這裏沒有使用。

+0

這與我的問題中的兩個例子不矛盾嗎?第一個十進制小數點後面有一個錯誤。除非我誤解了某些東西。 –

+1

啊,我誤解了。 15只是一個下界,要找出確切的數字,你將不得不做類似於你的上述計算。 –

1

要回答小數你的問題的雙精度浮點轉換部分...

小數的0.0和0.1之間的轉換將是很好的15-16 decimal digits(注:你開始在第一計數)

0.1 = 0.1000000000000000055511151231257827021181583404541015625有利於16位數(四捨五入到17它是0.10000000000000001;四捨五入到16它是0.1)。

0.2 = 0.200000000000000011102230246251565404236316680908203125也適用於16位數字。

(示例僅好爲15位數:

0.81 = 0.810000000000000053290705182007513940334320068359375)

+0

_「..將很好15-16十進制數字」__我假設你的意思是「有意義的」數字。另外,對於'0.1'到'10000.'範圍內的浮點數也是如此? –

+0

是,有效數字;是的,在這個範圍內也是15-16個數字。 –

相關問題