infinite while loop although I put break statement

Question:

this code is supposed to take slope (m) and y-intercept (b) of two lines and checks if these two line hit each other or not.
the problem is my while loop is infinite although I have condition and break statement

print("enter the first m: ")
m = input()  # m = slope

print("enter the first b: ")
b = input()  # b = y-intercept

print("enter the second m: ")
m1 = input()

print("enter the second b: ")
b1 = input()

sub_m = int(m) - int(m1) #sub = subtract
sub_b = int(b) - int(b1)

if (sub_m == 0):
    print("parallel")

x = float(-sub_b / sub_m)
r = round(x, 1)

i = 0.0
while i != r:

    print(r, i)
    if (i == r):
        print("nhit piont: ", i)
        break

    if (sub_m > 0 and sub_b > 0):
        i -= 0.1
    elif (sub_m < 0 and sub_b < 0):
        i -= 0.1
    else:
        i += 0.1
Asked By: Mustang

||

Answers:

This is a question of granularity and floating-point precision. You’re incrementing i in steps of 0.1 and then checking, at each step, if i == r. But what if r is not an integer multiple of 0.1? Then i will never exactly equal r, and your break will never be triggered.

By the way, your while condition and your if condition are mutually exclusive; if i and r are equal, you never enter the loop, and consequently won’t have to/be able to break out of it. What you want is probably a genuine infinite loop with while True.

Answered By: Schnitte

Running this in my debugger showed that you’re getting floating point representation errors. This means that although technically you should be getting numbers perfectly rounded to 1 decimal given that you’re applying increments of 0.1, in reality this isn’t the case:

enter image description here

As you can see, r = -2.0 and i = -2.00...4, thus at no point is r == i.

You can fix this by adding another round statement at the end:

print("enter the first m: ")
m = input()  # m = slope

print("enter the first b: ")
b = input()  # b = y-intercept

print("enter the second m: ")
m1 = input()

print("enter the second b: ")
b1 = input()

sub_m = int(m) - int(m1) #sub = subtract
sub_b = int(b) - int(b1)

if (sub_m == 0):
    print("parallel")

x = float(-sub_b / sub_m)
r = round(x, 1)

i = 0.0
while i != r:

    print(r, i)

    if (sub_m > 0 and sub_b > 0):
        i -= 0.1
    elif (sub_m < 0 and sub_b < 0):
        i -= 0.1
    else:
        i += 0.1
    i = round(i, 1)  # <- this

print(f"Hit pt: {i}")

HOWEVER: This is still error prone, and I recommend finding a way to avoid if i==r altogether in the code. If i is lower than r, exit the loop when it finally becomes bigger, and viceversa. Its best practice to avoid using the == condition when comparing floats, and to find a way to use <= and >=.

Answered By: Kike Laguilhoat

First of all, your while loop breaking condition contradicts your if() break condition. so it will never get to match the if condition. So it will never print hit point, because it will break the while loop when l==r, either it will never be l==r because of precision and loop infinite, so in both situations if condition never match. And comparing a floating value to break a loop is not ideal.

Answered By: akm elias

Probably because i will never be equal to r.
You might want to check if they are both ints.

Answered By: Fustigate

Everyone here seems to be adamant on using some fancy tricks to make floating comparison works. Why not just multiply it all by 10 and get rid of floats altogether? 🙂

I don’t know if it is the fastest solution but it should have less corner cases.

i = 0
while True: # <- condition removed to allow the "hit point" if to work

    print(r, i / 10)
    if (i == r * 10):
        print("nhit piont: ", i / 10)
        break

    if (sub_m > 0 and sub_b > 0):
        i -= 1
    elif (sub_m < 0 and sub_b < 0):
        i -= 1
    else:
        i += 1
Answered By: NO_NAME