简体   繁体   中英

Python gives me different outputs if I add a print() later on

I'm super new to programming and just wanted to make something to find the approximate value of x for the equation x^3 - 1 = x . I know that -2 is greater than 0 and -1 is less. My thought is that if I find the average and check if it's greater or less than 0 , I can redefine a and b and repeat until I get an approximate value. I've been having a hard time getting it to act right though. For example if I run this block without the print(i), I'll get -1.5 which would be the average, but when I put a print(total) within the function equation(n) to see if it's working right, it doesn't even show me that and just outputs -8.881784197001252e-16 . If I put print(i) at the end of the if/else possibilities, such as this, it prints 16 and then -8.881784197001252e-16 . I'm using PyCharm CE.

Beyond this glitch, is my logic correct? By setting the placeholder to 1 it will run the while loop. The while loop will get a new value of n and run the function, compare it to 0 , then reassign a or b depending on that comparison? Thanks in advance.

a = float(-2)
b = float(-1)
n = ((a+b)/2)
print(n)

def equation(n):

    total = float((n - n**3 - 1))

    return total

i = 1

while i != 0:
    n = ((a + b) / 2)
    if (equation(n)) > 0.0:
        a = n
        i = equation(n)
        print(i)

    else:
        b = n
        i = equation(n)
        print(i)

Moving all of the equation x^3 - 1 = x to one side should give x^3 - 1 - x = 0 or x - x^3 + 1 = 0 . You have a different equation in your function.

Another problem is that there is no intersection between the two equations between x=-2 and x=-1 (see here ). You'll need to expand your window to x=2 before you'll see an intersection.

Something that often happens in numerical analysis (where you'll see this type of problem) is that rather than trying to find x that actually makes the equation give 0 , we look for a value of x that produces below an acceptable level of error. Another approach is to test for while b - a > tol:

If we use all of this to tweak what you've got, you'll have

a = float(-2)
b = float(2)
tol = 0.001

def equation(n):
    return float(n - n**3 + 1)

n = (a + b) / 2
iter = 0
while abs(equation(n) - 0) > tol and iter < 100:
    iter+=1

    if equation(n) > 0.0:
        a = n
    else:
        b = n

    n = (a + b) / 2

    print(iter,a,b,equation(n))

Note: this works fine if you remove the floats and just do

a = -2
b = 2
#...etc

because python already recasts values as necessary. Try

>>> type(3)
<class 'int'>
>>> type(3.5)
<class 'float'>
>>> type(float(3))
<class 'float'>
>>> type(3/5)
<class 'float'>

so python will store the result as a float as soon as it is necessary.

The immediate problem is the limited precision of floats. If you print a and b after a hundred iterations, you get:

a, b = -1.324717957244746, -1.3247179572447458
print((a + b) / 2  # -1.3247179572447458, the same as b

So at some point, b never changes, which is why you get an infinite loop. If we evaluate equation at the average of a and b , you'll get -8.881784197001252e-16, the value you were always seeing.

But this will never converge to exactly zero because the solution is irrational , so even if you had infinite precision, equation would never equal zero.

The common way to resolve this issue is to avoid comparing floats:

if a == b               # don't do this
if abs(a - b) < epsilon      # do this, where epsilon is some small value

(Note: what you're describing is the bisection method , which is slower than higher order algorithms eg Newton's method, which you can use since you can get the derivative)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM