此代码有什么问题?我应该得到336108797689259276,但我得到的却是336108797689259264

时间:2019-09-04 05:01:32

标签: python-3.x

强大的叛军

Problem 346

数字7是特殊的,因为7是2的基数写成111,而6的基数写成11。 (即71_0 = 11_6 = 111_2)。换句话说,7是至少两个碱基b> 1中的一个repunit。

我们将具有此属性的正整数称为强重复单元。可以验证在50以下有8个强重复单元:{1,7,13,15,21,31,40,43}。 此外,低于1000的所有强重复单元的总和等于15864。 找到1012以下的所有强重复单元的总和。


此代码适用于项目欧拉问题346

import math
import time
start=time.time()
List=[1]
for i in range(2,1000000):
    summ=1+i+math.pow(i,2)
    power=2
    while summ<10**12:
        List.append(summ)
        power+=1
        summ+=math.pow(i,power)
List=(list(dict.fromkeys(List)))
print(sum(List)//1000000000,sum(List)%1000000000)
end=time.time()
print(end-start)

预期输出为336108797.0 689259276.0,但实际输出为336108797.0 689259264.0

1 个答案:

答案 0 :(得分:1)

我对这个问题感兴趣,并提出了这个建议:

from math import ceil, log2


def n_ones_to_base(e, base):
    """
    ~ int(e*"1", base)
    """
    p = 1
    ret = 1
    for _ in range(e - 1):
        p *= base
        ret += p
    return ret


def findall(limit):
    ret = {1}  # 1 somehow counts as repunit...
    # e is the number of repeated 1s
    # e=2, base=n-1 is always a solution; only look for other solutions
    # minial base = 2  -> maximal e ~ log2(limit)
    for e in range(3, ceil(log2(limit)) + 1): 
        for base in range(2, limit):
            n = n_ones_to_base(e, base)
            if n > limit:
                break
            ret.add(n)
    return ret


ret = findall(limit=10 ** 12)
s = sum(ret)
print(f"{divmod(s, 1000000000)}")
# (336108797, 689259276)

比较版本并进行挖掘,看来您正在使用math.pow(因此是floats)遇到舍入错误。如果您将所有pow(i, power)替换为i**power,则会得到正确的结果。

您的List中的元素与我的set ret中的元素相同-因此,舍入误差似乎仅源于sum:我的总和{ {1}},而您的s = 336108797689259276(这样的精度不足以将数字正确表示为最低有效十进制数字),

如果您将总和的sum(List) = 3.3610879768925926e+17high部分分开(使用low,总和为md = 1000000000),则可以使用浮点数:

high * md + low