【问题标题】:Perfect integer evaluation fails with input 343完美整数评估失败,输入 343
【发布时间】:2015-08-21 04:32:11
【问题描述】:

完美幂是一个正整数,可以表示为另一个正整数的整数幂。

任务是检查给定整数是否是完美幂。

这是我的代码:

def isPP2(x):
    c=[]
    for z in range(2,int(x/2)+1):

        if (x**(1./float(z)))*10%10==0:
            c.append(int(x**(1./float(z)))), c.append(z)
    if len(c)>=2:
        return c[0:2]
    else:
        return None

它适用于所有数字,例如:

isPP2(81)
[9, 2]
isPP2(2187)
[3, 7]

但它不适用于343 (73)。

【问题讨论】:

  • 在提出问题时,请尝试始终以对尽可能多的其他人有用的方式提出问题(有类似问题)。例如,标题“完美整数评估失败,输入 343”会更有意义。还请更准确地描述由此产生的问题,然后“不起作用”。它会崩溃吗?导致错误的结果?还是别的什么?
  • 感谢您的建议。我是新来的,对不起

标签: python math


【解决方案1】:

由于其他答案已经解释了为什么你的算法失败了,我将集中精力提供一种替代算法来避免这个问题。

import math

def isPP2(x):
    # exp2 = log_2(x) i.e. 2**exp2 == x 
    # is a much better upper bound for the exponents to test,
    # as 2 is the smallest base exp2 is the biggest exponent we can expect.
    exp2 = math.log(x, 2)
    for exp in range(2, int(exp2)):
        # to avoid floating point issues we simply round the base we get
        # and then test it against x by calculating base**exp
        # side note: 
        #   according to the docs ** and the build in pow() 
        #   work integer based as long as all arguments are integer.
        base = round( x**(1./float(exp)) ) 
        if base**exp == x:
            return base, exp

    return None

print( isPP2(81) )        # (9, 2)
print( isPP2(2187) )      # (3, 7)
print( isPP2(343) )       # (7, 3)
print( isPP2(232**34) )   # (53824, 17)

与您的算法一样,如果有多个解决方案,它只会返回第一个解决方案。

【讨论】:

    【解决方案2】:

    正如link 中所解释的,浮点数并不能完美地存储在计算机中。基于浮点计算中持续存在的这个非常小的差异,您很可能在计算中遇到一些错误。

    当我运行您的函数时,方程 ((x ** (1./float(z))) * 10 % 10) 的结果是 9.99999999999999986不是 10 符合预期。这是由于浮点运算中涉及的轻微错误。

    如果您必须将值计算为浮点数(这对您的总体目标可能有用也可能没有用),您可以为结果定义准确度范围。一个简单的检查看起来像这样:

    precision = 1.e-6    
    
    check = (x ** (1./float(z))) * 10 % 10
    if check == 0:
        # No changes to previous code
    elif 10 - check < precision:
        c.append(int(x**(1./float(z))) + 1)
        c.append(z)
    

    precision 以科学计数法定义,等于1 x 10^(-6)0.000001,但如果如此大的精度范围引入了其他错误,则可以降低幅度,这不太可能但完全有可能。我在结果中添加了1,因为原始数字小于目标。

    【讨论】:

    • 谢谢。我只是尝试使用数学方法来解决任务。请看这个:bymath.net/studyguide/alg/sec/alg17h.gif
    • 好答案,但也许最好使用标准库函数 round() 将浮点结果强制为最接近的整数。
    • 当然。我是 python 的菜鸟,但我用 C++ 做了很多科学计算。我不知道库和助手,但我可以手动做一些有意义的事情。也许round() 不会给出想要的结果。 @PaulCornelius
    【解决方案3】:

    因为343**(1.0/float(3)) 不是7.0,它是6.99999999999999。您正在尝试用浮点数学解决整数问题。

    【讨论】:

    • 但是 (8**(1./3.)) - 是 2。为什么 343 变成 .99999?
    • 因为计算机表示浮点数的方式以及标准数学函数中固有的舍入误差。请参阅http://en.wikipedia.org/wiki/Floating_point 了解比您想知道的更多详细信息。
    猜你喜欢
    • 2018-03-31
    • 2013-07-15
    • 2014-07-28
    • 1970-01-01
    • 2020-09-16
    • 2016-06-12
    • 2020-04-21
    • 1970-01-01
    • 2017-01-11
    相关资源
    最近更新 更多