【问题标题】:Sum of the series. What's wrong with this Python code?系列的总和。这个 Python 代码有什么问题?
【发布时间】:2014-10-23 15:38:44
【问题描述】:

我正在尝试编写一个程序来查找给定 n 以下所有 3 的倍数的总和。 到目前为止,我想出了这个解决方案(使用算术级数公式):

def sumof3(n):
    n = int((n-1)/3)
    return int((n/2)*(6+3*(n-1)))

它工作得很好,但由于某种原因开始大量失败。例如,对于 n = 232471924 返回值为 9007199280122284,而应该是 9007199280122283。

谁能告诉我这里的错误在哪里?

【问题讨论】:

  • 你用的是什么版本的 Python?

标签: python debugging sum-of-digits


【解决方案1】:

Python 有任意精度的整数,但有标准的有限(双)精度浮点数。在 Python 3 中,两个整数与/ 相除会产生一个浮点数,这意味着(例如)

>>> 10**50/10**25
1e+25
>>> int(10**50/10**25)
10000000000000000905969664

但如果我们使用// 纯粹处理整数,我们会得到:

>>> 10**50//10**25
10000000000000000000000000

在您的代码中,(n-1)/3(n/2) 都将产生浮点输出,这意味着您只有大约 18 位左右的精度。如果我们将您的函数重新设计为纯粹使用整数:

def sumof3b(n):
    n = (n-1)//3
    return (6+3*(n-1))*n//2

然后我们就低值达成一致:

>>> all(sumof3(n) == sumof3b(n) for n in range(10**7))
True

但在较高的值下,我们会保持精度:

>>> n = 232471924
>>> sumof3(n) # bad
9007199280122284
>>> sumof3b(n) # good
9007199280122283

[在这里我们可以重新排序以确保我们不会丢失任何小数数据,但我有时发现fractions 模块也很方便。]

【讨论】:

    【解决方案2】:

    这是round-off error 的示例:

    将无限多个实数压缩为有限位数需要一个近似表示。尽管整数有无限多,但在大多数程序中,整数计算的结果可以存储在 32 位中。相反,给定任何固定位数,大多数实数计算将产生无法使用那么多位精确表示的量。因此,浮点计算的结果必须经常四舍五入以适应其有限表示。这种舍入误差是浮点计算的特征。

    通过执行以下操作,您将足够接近您想要到达的位置:

    def sumof3(n):
        n = float((n-1)/3)
        return int((n/2)*(6+3*(n-1)))
    

    或者如果你想更精确:

    def sumof3(n):
        n = float((n-1)/3)
        return float((n/2)*(6+3*(n-1)))
    

    【讨论】:

      【解决方案3】:

      这对int来说太大了

      import sys
      print int(sys.maxint)
      print int(sys.maxint*2)
      

      对我来说它打印出来

      2147483647
      -2
      

      骗我!误解了问题!对不起!

      【讨论】:

      • 嗯,必须是特定于实现的行为。在 CPython 2.7.2 上,当我运行它时,我得到了 21474836474294967294
      • 凯文。在将 int() 添加到打印件之前,我得到了相同的结果。一开始是print sys.maxint*2。你这样做了吗?
      • 是的,我的int()s 已就位。 here 就是我所看到的。
      • 9007199163886320 在 2.7 中,9007199280122284 在 3.4.0 中。
      • 噢,愚蠢的我!我真的认为 op 的问题是完全不同的结果(因为数字太大)机器人实际上只是舍入问题......关于我们的案例......我必须同意它应该是特定于实现的行为
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-07
      相关资源
      最近更新 更多