Mustang
Mustang

Reputation: 1

infinite while loop although I put break statement

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

Upvotes: 0

Views: 1799

Answers (4)

Piotr Siupa
Piotr Siupa

Reputation: 4838

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

Upvotes: 1

Laguilhoat
Laguilhoat

Reputation: 323

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 >=.

Upvotes: 0

akm elias
akm elias

Reputation: 238

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.

Upvotes: 0

Schnitte
Schnitte

Reputation: 1217

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.

Upvotes: 0

Related Questions