【问题标题】:Why Python Decimal sum is not commutative (different result when I change the order)为什么 Python Decimal sum 不可交换(更改顺序时结果不同)
【发布时间】:2021-01-19 02:36:57
【问题描述】:

我使用带字符串的 Decimal 来避免典型问题

我有两个字典,它们具有相同的键和值,但键的顺序不同。 这些字典的值之和应该为零。但是,当我按一定顺序对它们求和时,它不是零。

这些是我的字典和我为确保值相同而进行的比较:

a = {'key_A': Decimal('0'),
    'key_B': Decimal('-1002708'),
    'key_C': Decimal('3965.5752'),
    'key_D': Decimal('991393.8'),
    'key_E': Decimal('-991393.8'),
    'key_F': Decimal('1173.30984201680672268907563'),
    'key_G': Decimal('-7348.6248'),
    'key_H': Decimal('6175.31495798319327731092437'),
    'key_I': Decimal('-741'),
    'key_J': Decimal('0'),
    'key_K': Decimal('4641'),
    'key_U': Decimal('-3900'),
    'key_L': Decimal('1038000'),
    'key_M': Decimal('0'),
    'key_N': Decimal('0'),
    'key_O': Decimal('0'),
    'key_P': Decimal('-3965.5752'),
    'key_Q': Decimal('0'),
    'key_R': Decimal('0'),
    'key_S': Decimal('-15570'),
    'key_T': Decimal('-19722')}

b = {'key_C': Decimal('3965.5752'),
    'key_D': Decimal('991393.8'),
    'key_B': Decimal('-1002708'),
    'key_K': Decimal('4641'),
    'key_U': Decimal('-3900'),
    'key_J': Decimal('0'),
    'key_A': Decimal('0'),
    'key_G': Decimal('-7348.6248'),
    'key_H': Decimal('6175.31495798319327731092437'),
    'key_I': Decimal('-741'),
    'key_R': Decimal('0'),
    'key_N': Decimal('0'),
    'key_T': Decimal('-19722'),
    'key_P': Decimal('-3965.5752'),
    'key_M': Decimal('0'),
    'key_L': Decimal('1038000'),
    'key_F': Decimal('1173.30984201680672268907563'),
    'key_O': Decimal('0'),
    'key_Q': Decimal('0'),
    'key_E': Decimal('-991393.8'),
    'key_S': Decimal('-15570')}

print(sorted(list(a.keys()))==sorted(list(b.keys()))) # "True" so the keys are the same

print(len(a), len(b)) # "21 21" the length are the same


keys = sorted(list(a.keys()))
for k in keys:
 assert a[k]==b[k] # never throws exception so the values are the same

sum_d = lambda d: sum(d[key] for key in d) # a function that sums all the values in a dictionary

问题来了:

print(sum_d(a), sum_d(b)) # "4E-22 0E-21" EVEN WHEN THE VALUES ARE THE SAME THE SUMS ARE NOT WTF

事情变得更奇怪了 我想确定这是因为顺序,所以我颠倒了顺序

a_new = {key:a[key] for key in b.keys()}
b_new = {key:b[key] for key in a.keys()}
  
print(sum_d(a_new), sum_d(b_new)) # "0E-21 4E-22" THE VALUES INVERTED SO IT IS BECAUSE OF THE ORDER

所以我的问题只是.....为什么...为什么 python sum 不是可交换的?

【问题讨论】:

    标签: python python-3.x floating-point decimal precision


    【解决方案1】:

    一般来说,浮点运算是不可交换的。 Decimal 类是浮点数。

    Decimal 算术运算的默认精度为 28 位。您可以通过更改上下文来更改它。例如,使用以下代码将精度提高到 40 位:

    import decimal
    decimal.getcontext().prec = 40
    

    如果您想为不精确的算术引发异常,您可以显式配置它。您可以显式设置上下文,例如:

    decimal.setcontext(decimal.Context(
        traps=[decimal.Inexact],
    ))
    

    【讨论】:

      【解决方案2】:

      b 中有两个“key_H”键。

      去掉b中的'key_H': Decimal('6175.31495798319327731092437'),行后,求和结果是一样的。

      【讨论】:

      猜你喜欢
      • 2013-11-18
      • 1970-01-01
      • 2014-08-06
      • 2014-09-21
      • 2023-02-11
      • 2013-10-27
      • 2013-11-19
      • 1970-01-01
      • 2021-11-13
      相关资源
      最近更新 更多