2014-04-01 27 views
4

對於長時間的問題以及對於不是真正最小的代碼,抱歉。Python新手如何解決浮點比較的問題

我對浮點比較的棘手有非常有限的理解。 我已閱讀了一些有關該主題的python文檔和教程。我讀過一些SO討論,如https://stackoverflow.com/a/4029397/1445400

但是,我不知道如何應用「爲什麼不使用str(value)」或「只用%格式化」或「您必須使用Decimal」等響應。我最喜歡的主題是「只是忽略小數點後第11位......它們並不重要,如果將響應格式化爲字符串,最終可以獲得正確的美學效果。」我不知道如何在我的應用程序中完成這項工作。

這是我的代碼,它可能看起來像作業,但真的不是。我正在計算跨越非矩形多邊形的網格線的交點。我生成一個矩形,移動一個或多個角點,然後繪製並重繪多邊形上的網格,所以我需要計算網格線開始,結束和交叉的位置。

def partition_boundaries(start, stop, number_of_partitions): 
    interval = (stop - start)/number_of_partitions 
    l = [start, stop] 
    i = 1 
    while i < number_of_partitions: 
     l.insert(i, start + i*interval) 
     i += 1 
    return l 

def test(): 
    test_cases = [ 
        ((0.0, 1.0, 2), [0, .5, 1]), 
        ((0.0, 1.0, 4), [0.0, 0.25, 0.5, 0.75, 1.0]), 
        ] 
    passes = 0 
    for (args, expected_result) in test_cases: 
     result = partition_boundaries(*args) 
     if result != expected_result: 
      print "Failed for: ", args, ". Expected: ", expected_result, " Got: ", result 
     else: 
      passes = passes + 1 
    print passes, " out of ", len(test_cases), " test cases passed." 

test() 

這將產生象輸出: 失敗爲:(0.0,1.0,4)。預計:[0.0,0.25,0.5,0.75000000000000011,1.0]獲得:[0.0,0.25,0.5,0.75,1.0]

相信這樣簡單的事情需要奧術演習,比如將數字轉換成字符串再返回,或者編寫我自己的功能來比較差異的絕對值和寬容度等。「這不應該是這麼難」,但也許我需要克服自己。這也讓我感到緊張,因爲我可以「輕輕地」將我的孩子介紹給「真正的」節目。

我不是在做財務會計,也不需要很多有意義的數字。

對於這段代碼,你如何推薦我繼續我的初學者教育?

回答

6

浮點平等測試是一件困難的事情。我不知道任何會改變語言內置的基本浮點比較的Python中的任何內容,但是如果兩個數字相近,可以寫出一個返回True的函數,其中可以用相對或絕對術語來定義接近,例如。

def almost_equal(x,y): 
    epsilon = 0.00001 
    return abs(x-y) < epsilon 

然後你會寫其他功能測試結構的「平等」,代替==使用almost_equal任何浮點比較。

0

瞭解浮點並不難。有兩件事要記住:1)就像在計算器中一樣,你只有有限的數字(通常在16左右)。 2)增量不是以十進制爲單位,而是在binary步驟中。隨着Numpy的幫助下,不同價值觀的分辨率可以很容易地確定:

import numpy as np 

for p in range(-5,5): 
    pp = 10**p 
    print("{:6g}: {}".format(pp, np.spacing(pp))) 

給出:

1e-05: 1.69406589451e-21 
0.0001: 1.35525271561e-20 
0.001: 2.16840434497e-19 
    0.01: 1.73472347598e-18 
    0.1: 1.38777878078e-17 
    1: 2.22044604925e-16 
    10: 1.7763568394e-15 
    100: 1.42108547152e-14 
    1000: 1.13686837722e-13 
10000: 1.81898940355e-12 

這意味着,例如,1 + 2.22044604925e-16 == 1False10 + 2.22044604925e-16 == 10True。正如@OldGeeksGuide指出,您需要根據幅度進行近似比較。請參閱Numpy的allclose()進行適當的比較