比较两个词典 - 浮点

时间:2013-04-28 17:45:44

标签: python

我试图在一段时间内解决这个问题,尝试搜索互联网并推荐一些书籍,但却无法找到解决方案。

这里提出了一种解决方案,但不确定是否还有其他更简单的方法。 请参阅:Comparing Python dicts with floating point values included

希望你能给出一些指示。

背景 有一个带有{key:{key:{key:[value]}}}关系的dict_A。该dict_A将经历迭代过程以基于若干约束和优化目标来优化其值。只有当最终优化的dict,即dict_B2等于dict优化的一个周期(即dict_B1)之前,才会停止优化过程。这给人的印象是dict不能进一步优化,这用于打破迭代周期。

问题: 由于dicts值包含浮点数,因此某些存储值会发生变化,这可能是因为字典以二进制格式存储值。请参阅下面的示例,字典中第一个浮点值的变化。

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]}}}

如果我使用下面的内容,则交互过程会进行无限循环而不会中断,

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,这是不正确的但是当代码被解除时,它才能正常工作。也许return all正在进行OR而不是AND。仍在排除故障。

如果您有任何提示,请分享。将继续努力解决这个问题。感谢Jakub和Julien到目前为止的所有指导。

RGDS Saravanan K

3 个答案:

答案 0 :(得分: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))

答案 1 :(得分:1)

正如您所解释的,您的代码会检查计算的解决方案是否等于上一步结果。问题可能在于您的算法在两个(或更多)解决方案之间振荡,这些解决方案彼此非常接近。

所以我认为你可以:

  • 存储多个先前结果,以检查您是否已进入循环。问题是要知道您需要存储多少先前的解决方案。
  • 或者,正如Jakub和您指出的帖子所建议的那样,您可以检查dict_B1是否在dict_B2的某个范围内。

第二种解决方案在您的情况下很痛苦,因为您的结构过于复杂。如果您不想破坏所有代码,可以将[value]替换为{key:{key:{key:[value]}}}中的自定义浮点类,该类重新定义__eq__()运算符以检查某个内的相等性范围。

答案 2 :(得分:0)

np.allclose 是比较两个浮点列表的便捷函数。

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

numpy.allclose(a,b,rtol = 1e-05,atol = 1e-08,equal_nan = False)

     

绝对(a - b)&lt; =(atol + rtol * absolute(b))`