2013-04-28 86 views
3

我試圖解決這個問題,嘗試搜索互聯網和引用一些書,但一直沒能找到解決方案。比較兩個字典 - 浮點

這裏提出了一種解決方案,但不確定是否還有其他更簡單的方法。 參考:Comparing Python dicts with floating point values included

希望你能給一些指點。

背景: 有dict_A附帶{key:{key:{key:[value]}}}關係。這個dict_A將通過一個迭代過程來基於幾個約束和一個優化目標來優化其價值。只有當最終優化的字典,即dict_B2與dict_B1之前的字典優化的一個週期相等時,才停止優化過程。這給人的印象是字典不能進一步優化,這被用來打破迭代週期。

問題: 由於字典值包含浮點數,所以某些存儲值會被更改,可能是因爲字典以二進制格式存儲值。請參考下面的例子,字典中第一個浮點值的變化。

dict_B1 = {0: {36: {3: [-1], 12: [0.074506333542951425]}}, 1: {36: {2: [-1], 16: [0.048116666666666676], 17: [-1]}}, 2: {}, 3: {36: {5: [-1], 6: [-1], 15: [0.061150932060349471]}}} 
dict_B2 = {0: {36: {3: [-1], 12: [0.074506333542951439]}}, 1: {36: {2: [-1], 16: [0.048116666666666676], 17: [-1]}}, 2: {}, 3: {36: {5: [-1], 6: [-1], 15: [0.061150932060349471]}}} 

如果我使用下面的Interative的過程進行無限循環,不打破,

if (dict_B1==dict_B2): 
    Exit 

,或者

if (cmp(dict_B1,dict_B2)): 
    Exit 

是否有任何其他的方式來比較的字典說,與來自18個浮點精度值的15個浮點精度進行比較?

我試圖在字典中存儲較小的精度值浮點數。問題仍然存在。

希望你能幫助我指出正確的方向。

更新1:的Jakub的建議

的Jakub的建議是好的。我可以創建兩個中間列表,即List_B1和List_B2來存儲浮點數,這些將用於比較和作爲一個標誌來決定何時打破迭代過程。

以下是用於測試案例的代碼。 List_B2中的第二項被故意改變,所以該值超出精度閾值。

def is_equal(floats_a, floats_b, precision=1e-15): 
    return all((abs(a-b) < precision) for a, b in izip(floats_a, floats_b)) 

List_B1=[0.074506333542951425,0.048116666666666676,0.061150932060349471] 
List_B2=[0.074506333542951439,9.048116666666666676,0.061150932060349471] 

print "is_equal(List_B1,List_B2):",is_equal(List_B1,List_B2) 

for a, b in izip(List_B1, List_B2): 
    print a,b, (abs(a-b) < 1e-15) 

結果:

is_equal(List_B1,List_B2): True 

0.074506333543 0.074506333543 True 
0.0481166666667 9.04811666667 False 
0.0611509320603 0.0611509320603 True 

奇怪is_equal函數總是返回TRUE這是不正確的,但在disected的代碼,它工作正常。也許return all正在做OR而不是AND。仍然排除故障。

如果您有任何提示,請分享。將繼續努力解決這個問題。感謝Jakub和Julien爲您提供的所有指導。

RGDS Saravananķ

回答

3

當比較浮點數,始終牢記漂浮不是無限的精度和累積誤差。你真正感興趣的是,如果兩個浮體足夠接近,不若如果你想測試他們是平等的

如果浮動的兩個列表都是平等的,我會做

def is_equal(floats_a, floats_b, precision=1e-15): 
    return all((abs(a-b) < precision) for a, b in izip(floats_a, floats_b)) 
+0

感謝您的幫助@Jakub M.已經測試過這個並且已經提交了我的更新,如上所述。將繼續工作並更新所有 – 2013-04-28 19:10:27

1

正如你解釋,你的代碼檢查計算得到的解決方案是否與上一步結果相同。問題可能是您的算法在兩個(或更多)彼此非常接近的解決方案之間振盪。

所以我認爲你可以:

  • 存儲幾個以前的結果,檢查是否已進入了一個循環。問題是要知道你需要存儲多少以前的解決方案。
  • 或者,正如Jakub和您指出的帖子所建議的,您可以檢查dict_B1是否在dict_B2的某個範圍內。

第二種解決方案在您的情況下很痛苦,因爲您的結構太複雜。如果您不想破壞所有代碼,則可以用{key:{key:{key:[value]}}}中的[value]替換爲自定義浮動列表類,它重新定義__eq__()運算符以在一定範圍內檢查相等性。

+0

謝謝Julien。探索Jakub的建議,似乎更簡單。如果卡住會嘗試你的 – 2013-04-28 19:12:04

1

np.allclose是一個方便的函數來比較兩個浮點列表。

>>> import numpy as np 
>>> np.allclose(List_B1, List_B2) 
False 

numpy.allclose(A,B,RTOL = 1E-05,蒂= 1E-08,equal_nan =假)

絕對(一 - 二)< =(蒂+ RTOL *絕對(b))`