计算每个数字的4次幂的总和,为什么我得到错误的结果?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算每个数字的4次幂的总和,为什么我得到错误的结果?相关的知识,希望对你有一定的参考价值。

我正在尝试完成Project Euler question #30,我决定根据已知答案验证我的代码。基本上问题是:

找到所有可写入的数字之和,作为其数字的五次幂之和。

以下是我试图用python证明的已知答案:

1634 = 1^4 + 6^4 + 3^4 + 4^4 8208 = 8^4 + 2^4 + 0^4 + 8^4 9474 = 9^4 + 4^4 + 7^4 + 4^4

由于1 = 1 ^ 4不是总和,因此不包括在内。

这些数字的总和是1634 + 8208 + 9474 = 19316。

当我运行我的代码时,我得到所有三个值加起来为19316,太棒了!然而,在这些值中有一个不正确的值:6688

这是我的代码:

i=1
answer = []

while True:
    list = []
    i=i+1
    digits = [int(x) for x in str(i)]

    for x in digits:
        a = x**4
        list.append(a)

        if sum(list) == i:
            print(sum(list))
            answer.append(sum(list))

list的总和返回三个正确的值,值为6688。任何人都可以发现我错过的东西吗?

答案

你太早检查这笔钱。您检查数字中每个数字的匹配总和,6 ^ 4 + 6 ^ 4 + 8 ^ 46688。这是三位数,而不是全部四位数。

将你的sum()测试移出你的for循环:

for x in digits:
    a = x**4
    list.append(a)

if sum(list) == i:
    print(sum(list))
    answer.append(sum(list))

当总和已经超过目标时,你最多可以提前丢弃一个数字:

digitsum = 0
for d in digits:
    digitsum += d ** 4
    if digitsum > i:
        break
else:
    if digitsum == i:
        answer.append(i)

但是我不打算在这里,只需使用生成器表达式来组合确定数字,将它们提升到4次幂,然后求和:

if sum(int(d) ** 4 for d in str(i)) == i:
    answer.append(i) 

你没有定义一个上限,数字总是大于它们的数字之和,你需要停止递增i。对于n次幂的总和,你可以通过取9 ^ n,计算其数字,然后取第n次方的9位乘以9的n次方来找到这样一个点。如果这样产生一个数字更多的数字,继续,直到位数不再变化。

同样,你可以在i开始max(10, 1 + 2 ** n),因为你能从数字中得到的最小总和将使用一个2数字加上你可以逃脱的最小数量的10数字,以及任何数字当大于1时,1和0以外的数字的幂总是大于数字值本身,你不能使用i = 1

def determine_bounds(n):
    """Given a power n > 1, return the lower and upper bounds in which to search"""
    nine_power, digit_count = 9 ** n, 1
    while True:
        upper = digit_count * nine_power
        new_count = len(str(upper))
        if new_count == digit_count:
            return max(10, 2 ** n), upper
        digit_count = new_count

如果将上述函数与传递给range(*<expression>)range()变长参数结合使用,则可以使用for循环:

for i in range(*determine_bounds(4)):
    # ...

你可以确定一个数字是否等于函数中给定幂n的数字总和:

def is_digit_power_sum(i, n):
    return sum(int(d) ** n for d in str(i)) == i

然后你可以将所有内容放入列表理解中:

>>> n = 4
>>> [i for i in range(*determine_bounds(n)) if is_digit_power_sum(i, n)]
[1634, 8208, 9474]
>>> n = 5
>>> [i for i in range(*determine_bounds(n)) if is_digit_power_sum(i, n)]
[4150, 4151, 54748, 92727, 93084, 194979]

is_digit_power_sum()可以从权力的缓存中受益;添加缓存使得该功能的速度是4位数输入的两倍多:

def is_digit_power_sum(i, n, _cache=):
    try:
        powers = _cache[n]
    except KeyError:
        powers = _cache[n] = str(d): d ** n for d in range(10)
    return sum(powers[d] for d in str(i)) == i

当然,问题的解决方案是数字的总和:

n = 5
answer = sum(i for i in range(*determine_bounds(n)) if is_digit_power_sum(i, n))
print(answer)

使用Python 3.8.0a3,在我的2.9 GHz Intel Core i7 MacBook Pro上产生所需的输出不到半秒。

另一答案

这里修正:

i=1
answer = []

while True:
    list = []
    i=i+1
    digits = [int(x) for x in str(i)]

    for x in digits:
        a = x**4
       list.append(a)

       if sum(list) == i and len(list) == 4:
           print(sum(list))
           answer.append(sum(list))

我找到的错误: 6 ^ 4 + 6 ^ 4 + 8 ^ 4 = 6688 所以我只是检查列表的列表。

以上是关于计算每个数字的4次幂的总和,为什么我得到错误的结果?的主要内容,如果未能解决你的问题,请参考以下文章

矩阵n次幂的计算

怎样算次幂啊

分析涉及按位运算和 2 次幂的算法?

矩阵如何求幂?

javascript 如何计算几次方

C++中如何输入次幂