2013-04-28 84 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))`