使用输入343,完美整数评估失败

时间:2015-06-06 06:44:25

标签: python math

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

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

这是我的代码:

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

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:0)

如此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添加到结果中,因为原始数字小于目标。

答案 2 :(得分:0)

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

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)

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