0

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

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

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

有人可以建议这里的错误在哪里吗?

4

3 回答 3

3

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模块也很方便。]

于 2014-10-23T16:17:51.360 回答
0

这是一个舍入错误的示例:

将无限多个实数压缩为有限位数需要近似表示。尽管整数有无限多,但在大多数程序中,整数计算的结果可以存储在 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)))
于 2014-10-23T15:55:09.390 回答
0

它太大了int

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

对我来说它打印

2147483647
-2

糊弄我!误解了问题!对不起!

于 2014-10-23T15:55:10.243 回答