Python - Project Euler #80,理解错误

Python - Project Euler #80, understanding the error

欧拉计划问题 #80 似乎很简单:

https://projecteuler.net/problem=80

使用小数模块计算给定精度的平方根:

from decimal import Decimal, localcontext

def prob80():
    total = 0
    for x in range(1,100):
        with localcontext() as ctx:
            ctx.prec = 100
            total+=sum([int(i) for i in str(Decimal(x).sqrt())[2:]])
    return total
print prob80()

I return 40308 我的理解与正确答案有些偏差。对于前十位自然数的平方根的数字和 I return:

0 475 441 0 472 470 397 463 0 456

哪里出错了?我认为这是由于某种舍入误差造成的,但我似乎无法解决。

http://blog.dreamshire.com/project-euler-80-solution/

First, the 100 digits include digits to the right and left of the decimal.

Second, make sure to calculate more digits than are necessary to avoid rounding errors as it affects some of the numbers.

from decimal import Decimal, localcontext

def prob80():
    total = 0
    for x in range(1,100):
        print x
        with localcontext() as ctx:
            ctx.prec = 105
            if len(str(Decimal(x).sqrt())) == 1:
                total+=0
            else:
                a = sum([int(i) for i in str(Decimal(x).sqrt())[2:101]])+int(str(Decimal(x).sqrt())[0])
                total+=a
    return total
print prob80()

你犯了两个错误,这两个错误在示例案例中相互抵消了。

  1. 你没有数到第一个数字1
  2. 您将精度设置得太低了一位。最后一位几乎总是包含一些舍入误差。 sqrt(2) 的第 100 位和第 101 位是 27,因此当您使用 prec=100 时,它被四舍五入为 3,弥补了第一个错误。

顺便说一句。有一个简单的实现。 Decimal 对象有 as_tuple() 方法:

Return a named tuple representation of the number: DecimalTuple(sign, digits, exponent).

所以你可以选择:

decimal.getcontext().prec = 101
i = 2
sum(decimal.Decimal(i).sqrt().as_tuple()[1][:100]) # [1] is `digits`; [:100] are 1st 100

不需要字符串转换,也不需要 "iffing"。