0

プロジェクト オイラーの問題 #80 は単純に見えます。

https://projecteuler.net/problem=80

decimal モジュールを使用して、指定された精度で平方根を計算します。

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()

私は 40308 を返しますが、これは正しい答えからはずれていると理解しています。最初の 10 個の自然数の平方根のデジタル和については、次のように返します。

0 475 441 0 472 470 397 463 0 456

ここのエラーはどこですか?ある種の丸め誤差が原因だと思いますが、解決できないようです。

4

2 に答える 2

3

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

まず、100 桁には、小数点の右側と左側の桁が含まれます。

次に、丸め誤差が一部の数値に影響するため、丸め誤差を回避するために、必要以上の桁数を計算するようにしてください。

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()
于 2016-06-08T16:03:05.753 に答える
2

例のケースでは、互いに打ち消し合う 2 つの間違いを犯しました。

  1. 1桁目に数えていません1
  2. 設定した精度が 1 桁低すぎます。最後の桁には、ほとんどの場合、丸め誤差が含まれています。の 100 桁目と 101 桁目sqrt(2)27であるため、使用prec=100すると に切り上げられ3、1 番目の誤差が埋められます。

ところで。簡単な実装があります。Decimalオブジェクトにはas_tuple()メソッドがあります:

数値の名前付きタプル表現を返します: 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" は必要ありません。

于 2016-06-08T16:37:27.803 に答える