3

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

这里提出了一种解决方案,但不确定是否还有其他更简单的方法。请参阅:将 Python dicts 与包含的浮点值进行比较

希望大家能给点指点。

背景: 拥有带有 {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 萨拉瓦南 K

4

3 回答 3

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))
于 2013-04-28T17:53:42.390 回答
1

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

所以我认为你可以:

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

第二种解决方案在您的情况下很痛苦,因为您的结构太复杂了。如果你不想破坏你的所有代码,你可以用[value]一个{key:{key:{key:[value]}}}自定义的浮动列表类替换它,它重新定义__eq__()运算符来检查一定范围内的相等性。

于 2013-04-28T18:32:54.740 回答
1

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)<=(atol + rtol * 绝对(b))`

于 2017-09-05T03:20:32.610 回答