在Python 3中使用二分法搜索的Cube root:-1到0中的数字

wyyhbhjk  于 12个月前  发布在  Python
关注(0)|答案(3)|浏览(123)

下面是我的代码,它似乎不适用于-1和0之间的数字(否则工作得很好)
我认为代码进入了一个无限循环,不知何故,因此我输入数字后没有结果。请看一下,让我知道应该做什么修改。我是一个初学者在编程,并将感谢任何帮助!

cube = float(input('Enter:'))
if abs(cube) > 1:
    num_guesses = 0
    epsilon = 0.0001
    low = 0
    high = cube
    guess = (high + low) / 2.0

    while abs(abs(guess) ** 3 - abs(cube)) >= epsilon:
        if cube > 0:
            if guess ** 3 < cube:
                low = guess
            else:
                high = guess
            guess = (low + high) / 2.0
            num_guesses += 1
        else:
            if guess ** 3 > cube:
                low = guess
            else:
                high = guess
            guess = (low + high) / 2.0
            num_guesses += 1

if abs(cube) < 1:
    num_guesses = 0
    epsilon = 0.0001
    low = cube
    high = 1
    guess = (high + low) / 2.0

    while abs(abs(guess) ** 3 - abs(cube)) >= epsilon:
        if cube > 0:
            if guess ** 3 < cube:
                low = guess
            else:
                high = guess
            guess = (low + high) / 2.0
            num_guesses += 1
        else:
            low = -1
            high = cube
            if guess ** 3 > cube:
                high = guess
            else:
                low = guess
            guess = (low + high) / 2.0
            num_guesses += 1

print(num_guesses)
print('The cube root of',cube,'is closest to',guess)

字符串
多谢了!

8wigbo56

8wigbo561#

Python_3实现使用二分法求立方根。
您可以创建函数来进一步简化它

x=input("Please Enter a number")
    try:
    cube=float(x)
    except:
        print("Invalid Entry")

字符串
对于0和1之间或0和-1之间的数字

if (cube>0 and cube<1) or (cube>-1 and cube<0):  
         low=abs(cube)
         high=1


对于大于1且小于-1的数字

else:
         if cube>=1 or cube<=-1:
             low=0
             high=abs(cube)


使用二分法初始化猜测

guess=(low+high)/2.0


声明误差幅度并计算近似猜测(二分法)

epsilon=0.001
    while abs(guess**3-abs(cube))>epsilon:
        if guess**3<abs(cube):
            low=guess
        else:
            high=guess
    
        guess=(low+high)/2.0


最终输出

if cube>0:
        print("The cube root of ",cube,"is",guess)
    else:
        print("The cube root of ",cube,"is",-1*guess)

vcirk6k6

vcirk6k62#

通过将条件更改为

abs(guess ** 3 - cube) >= epsilon

字符串
事实上,你必须使用这个条件,而不是

abs(abs(guess) ** 3 - abs(cube)) >= epsilon


因为后者可能会给予假肯定(并因此过早地退出while-loop)。例如,如果guess等于2且cube等于-8,则后一个条件为True,即使2不是-8的立方根。

In [65]: guess, cube, epsilon = 2, -8, 0.0001

In [67]: abs(abs(guess) ** 3 - abs(cube)) >= epsilon
Out[67]: False  <-- would cause the while-loop to abort prematurely

In [68]: abs(guess ** 3 - cube) >= epsilon
Out[68]: True


注意,在你的代码中,有时low可以大于high。例如,如果cube < 0,那么lowhigh是这样初始化的:

if abs(cube) > 1:
    low = 0
    high = cube


特别是因为我们是二等分的,如果我们可以依赖于low总是<= high,这将是有帮助的。如果我们记录并遵守一个自我强加的编码契约low <= high,如果我们另外选择lowhigh,使得立方根总是在lowhigh之间,那么代码就变得简单多了:

cube = float(input('Enter:'))

num_guesses = 0
epsilon = 0.0001

# Coding contract: low <= (cube root of cube) <= high
low = min(cube, -1)
high = max(cube, 1)

guess = (high + low) / 2.0

while abs(guess ** 3 - cube) >= epsilon:
    if guess ** 3 < cube:
        low = guess
    else:
        high = guess
    guess = (low + high) / 2.0
    num_guesses += 1

print('num_guesses = {}'.format(num_guesses))
print('The cube root of',cube,'is within epsilon of',guess)
print('{}**3 = {}'.format(guess,guess**3))


不再需要处理abs(cube) > 1abs(cube) < 1cube > 0cube <=0的情况。所有cube的值都可以以相同的方式处理,因为guess**3 - cubeguess的单调递增函数。如果guess**3 > cube,如果guess太大,则减少guess。如果guess**3 < cubeguess太小,则增加猜测。由于我们知道low <= high,因此如何调整lowhigh的逻辑变得简单。
顺便说一下,在你的原始代码中,

else:
    low = -1
    high = cube


在最后一个else子句中的行是代码陷入无限循环的部分原因。lowhigh只应该初始化一次。将这些行放在while循环中会将lowhigh重置为一个宽的、简单的间隔,并丢弃之前的二分法迭代所做的工作。

c7rzv4ha

c7rzv4ha3#

下面是一个通过对分搜索求n次方根的脚本(修改自第4讲here)。

def findRoot(pwr, val, epsilon):
    assert type(pwr) == int and type(val) == float and type(epsilon) == float
    assert pwr > 0 and epsilon > 0
    low = 0  
    high = max(abs(val), 1.0)
    pos_ans = (high + low)/2.0
    while abs(pos_ans**pwr - abs(val)) >= epsilon:
        if pos_ans**pwr < abs(val):
            low = pos_ans
        else:
            high = pos_ans
        pos_ans = (high + low)/2.0
    if pwr%2 == 0 and val < 0:
        return None
    elif pwr%2 == 0 and val >= 0:
        return pos_ans
    elif pwr%2 != 0 and val < 0:
        return -pos_ans
    elif pwr%2 != 0 and val >= 0:
        return pos_ans

字符串
它返回x,使得abs(xr-瓦尔)<= 0。
例如findRoot(5,-0.734,10
(-5))返回-0.9400253295898438。结果可以由其他计算器检查。
下面是一个单行编辑,它还打印了所涉及的间隔:

def findRoot(pwr, val, epsilon):
    assert type(pwr) == int and type(val) == float and type(epsilon) == float
    assert pwr > 0 and epsilon > 0
    low = 0  
    high = max(abs(val), 1.0)
    pos_ans = (high + low)/2.0
    while abs(pos_ans**pwr - abs(val)) >= epsilon:
        if pos_ans**pwr < abs(val):
            low = pos_ans
        else:
            high = pos_ans
        pos_ans = (high + low)/2.0
        print(['low = ' + str(low), 'high = ' + str(high) , 'pos_ans = ' + str(pos_ans)])   
    if pwr%2 == 0 and val < 0:
        return None
    elif pwr%2 == 0 and val >= 0:
        return pos_ans
    elif pwr%2 != 0 and val < 0:
        return -pos_ans
    elif pwr%2 != 0 and val >= 0:
        return pos_ans


下面是findRoot(5,-0.734,10**(-5))的结果:
x1c 0d1x的数据

相关问题