infinite while loop although I put break statement - python

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

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

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

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.

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.

Related

How do I write a for loop in Python to repeatedly ask the user to enter a number until they enter in a whole number (0, 1, 2, etc)?

I know how to do this with a while loop and know how to use a for-loop in other languages like Java and C++. I want to use a for-loop in place of where I have written the while loop asking for the user input.
# You are required to use for-loop to solve this and round your answer to 2 decimal places. Write
# a program that takes n ∈ N (i.e., any positive integer including zero) from the user and use the
# input value to compute the sum of the following series:
n = -1
while n < 0:
n = int(input("Enter a value to compute: "))
# keep asking for user input until a whole number (0, 1, 2, 3, etc...) has been entered
k = 0
sum = 0
# To hold the sum of the fraction to be displayed
lastTerm = 0
# This variable represents the last term to be added to the fraction sum before the while loop below terminates
if n == 0:
sum = 0
elif n == 1:
sum = 1
else:
while lastTerm != 1 / n:
lastTerm = (n - k) / (k + 1)
sum = sum + (n - k) / (k + 1)
k += 1
print("{:.2f}".format(sum))
# Print the sum to two decimal places
One option is to catch the exception which is thrown when you cannot convert the input to an int, i.e.
while(True):
try:
# read input and try and covert to integer
n = int(input("Enter a value to compute: "))
# if we get here we got an int but it may be negative
if n < 0:
raise ValueError
# if we get here we have a non-negative integer so exit loop
break
# catch any error thrown by int()
except ValueError:
print("Entered value was not a postive whole number")
Alternative, slightly cleaner but I'm not 100% sure isdigit() will cover all cases
while(true):
n = input("Enter a value to compute: ")
if value.isdigit():
break
else:
print("Entered value was not a postive whole number")
How about this? It uses the for loop and sums all the values in the list.
x=[1,2,3,4] #== test list to keep the for loop going
sum_list=[]
for i in x:
j=float(input("Enter a number: "))
if not j.is_integer() or j<0:
sum_list.append(j)
x.append(1) #=== Add element in list to keep the cyclone going
else:
break
sums=sum(sum_list)
print("The Sum of all the numbers is: ",round(sums,2))
Use this to check for whole numbers -
if num < 0:
# Not a whole number
elif num >= 0:
# A whole number
for a for loop:
import itertools
for _ in itertools.repeat([]): # An infinite for loop
num = input('Enter number : ')
if num < 0:
# Not a whole number
pass # This will ask again
elif num >= 0:
# A whole number
break # break from for loop to continue the program
Easier Way -
mylist = [1]
for i in mylist : # infinite loop
num = int(input('Enter number : '))
if num < 0:
mylist.append(1)
pass # This will ask again
elif num >= 0:
# A whole number
break

Why is my code running infinitely?

this is an even odd calculator that runs infinitely without any errors. Does anyone know how to fix this? Is it ok for me to call the method with the input from times?
def calc(time):
i = 1
while i <= time:
num = int(input("Enter your number"))
i + 1
x=0
y=0
if (int(num) % 2 == 0):
even = True
print("even")
elif (int(num) % 2 != 0):
odd = True
print("odd")
if (odd == True):
x += 1
elif (even == True):
y += 1
times = int(input("How many numbers will you be putting in this calc?"))
calc(times)
Just a few things you have wrong, the rest are pretty good, explain are in the comments:
All the variables in [x, y , even , odd] are useless at all, so that's why I erased them.
def calc(time):
i = 1
while i <= time:
num = int(input("Enter your number"))
i+=1 # important thing here, to update the value the symbol is +=, not just +
if (int(num) % 2 == 0):
print("even")
else: # there is no need of elif, if the number is not even, by definition, it is odd
print("odd")
times = int(input("How many numbers will you be putting in this calc?"))
calc(times)
you can try it here, and see how do correctly the job :) -> https://repl.it/Nm70/0
Line number 5 should be i = i+1
I'm assuming you have a formatting issue with stackoverflow and not a formatting issue with your actual code. The lines after your while loop need to be indented which I'm assuming you are doing. The problem you have is that you aren't incrementing i. The first line after your input you have i + 1. That does nothing as you aren't assigning it to anything. You have x += 1 and y += 1 later on in your code which increments and assigns. So basically change your i+1 line to be i += 1 or i = i + 1
Everything that you want in the while loop needs to be indented by one "tab" like so:
while i <= time:
#Code goes here

Python script for finding keith numbers not working

I am trying to make a python program that will find keith numbers. If you don't what keith numbers are, here is a link explaining them:
Keith Numbers - Wolfram MathWorld
My code is
from decimal import Decimal
from time import sleep
activator1 = 1
while (activator1 == 1):
try:
limit = int(raw_input("How many digits do you want me to stop at?"))
activator1 = 0
except ValueError:
print "You did not enter an integer"
limitlist = []
activator2 = 1
while (activator2 <= limit):
limitlist.append(activator2)
activator2 += 1
print limitlist
add1 = 0
add = 0
count = 9
while 1:
sleep (0.1)
numbers = list(str(count))
for i in limitlist:
if (i > 0) & (add < count):
add = sum(Decimal(i) for i in numbers)
lastnumber = int(numbers[-1])
add1 = lastnumber+int(add)
numbers.reverse()
numbers.pop()
numbers.append(add1)
print add1
print add
print count
print numbers
if (add1 == count):
print"________________________________"
print add1
print count
elif (i > 0) & (add > count):
count += 1
break
It doesn't output any errors but it just outputs
18
9
9
[18]
Could someone please tell me why it doesn't just repeatedly find Keith numbers within the number of integers range?
You have it in front of you:
add1 = 18
add = 9
count = 9
numbers = [18]
You're in an infinite loop with no output. You get this for once. After this, i runs through the values 1, 2, and 3. Each time through the for loop, all three if conditions are False. Nothing changes, you drop out of the for loop, and go back to the top of the while. Here, you set numbers back to ['9'], and loop forever.
I suggest that you learn two skills:
Basic debugging: learn to single-step through a debugger, looking at variable values. Alternately, learn to trace your logic on paper and stick in meaningful print statements. (My version of this is at the bottom of this answer.)
Incremental programming: Write a few lines of code and get them working. After you have them working (test with various input values and results printed), continue to write a few more. In this case, you wrote a large block of code, and then could not see the error in roughly 50 lines. If you code incrementally, you'll often be able to isolate the problem to your most recent 3-5 lines.
while True:
# sleep (0.1)
numbers = list(str(count))
print "Top of while; numbers=", numbers
for i in limitlist:
print "Top of for; i =", i, "\tadd =", add, "\tcount =", count, "\tadll =", add1
if (i > 0) & (add < count):
add = sum(Decimal(i) for i in numbers)
lastnumber = int(numbers[-1])
add1 = lastnumber+int(add)
numbers.reverse()
numbers.pop()
numbers.append(add1)
print "add1\t", add1
print "add\t", add
print "count\t", count
print "numbers", numbers
if (add1 == count):
print"________________________________"
print add1
print count
elif (i > 0) & (add > count):
count += 1
print "increment count:", count
break
Prune has already given you good advices! Let's put a little example of what he meant though, let's say you got an algorithm which determine whether n is a keith number or not and also a test loop to print some keith numbers:
def keith_number(n):
c = str(n)
a = list(map(int, c))
b = sum(a)
while b < n:
a = a[1:] + [b]
b = sum(a)
return (b == n) & (len(c) > 1)
N = 5
for i in range(N):
a, b = 10**i, 10**(i + 1)
print("[{0},{1}]".format(a, b))
print([i for i in filter(keith_number, range(a, b))])
print('-' * 80)
such snippet gives you this:
[1,10]
[]
--------------------------------------------------------------------------------
[10,100]
[14, 19, 28, 47, 61, 75]
--------------------------------------------------------------------------------
[100,1000]
[197, 742]
--------------------------------------------------------------------------------
[1000,10000]
[1104, 1537, 2208, 2580, 3684, 4788, 7385, 7647, 7909]
--------------------------------------------------------------------------------
[10000,100000]
[31331, 34285, 34348, 55604, 62662, 86935, 93993]
--------------------------------------------------------------------------------
Wow, that's awesome... but wait, let's say you don't understand the keith_number function and you want to explore a little bit the algorithm in order to understand its guts. What about if we add some useful debug lines?
def keith_number(n):
c = str(n)
a = list(map(int, c))
b = sum(a)
print("{0} = {1}".format("+".join(map(str, a)), b))
while b < n:
a = a[1:] + [b]
b = sum(a)
print("{0} = {1}".format("+".join(map(str, a)), b))
return (b == n) & (len(c) > 1)
keith_number(14)
print '-' * 80
keith_number(15)
that way you'll be able to trace the important steps and the algorithm will make sense in your head:
1+4 = 5
4+5 = 9
5+9 = 14
--------------------------------------------------------------------------------
1+5 = 6
5+6 = 11
6+11 = 17
Conclusion: I'd advice you learn how to debug your own code instead asking strangers about it ;-)
I hope this solves your problem , and also I'm actually new here , so basically I solved it with the use of lists I hope u can understand :)
def kieth(n):
n1 = n[::-1]
f = [0]
[f.insert(0, int(x)) for x in n1]
for x in range(1, int(n)):
if f[-2] == int(n):
break
else:
f.insert(-1, sum(f[-abs(len(n1)) - 1:-1]))
return True if int(n) in f else False
n = input(" enter a number ")
print("is a kieth number " if kieth(str(n)) else "not a keith")

Python Code to Find x Prime Numbers w/ For Loop?

I am trying to put together a simple program which could work out n prime numbers. I would like to do this by using a nested for loop, where one would go through the numbers, and another would divide that number by all of the numbers up to it to see if it would be divisible by anything.
The problem I am having is that in the main for loop, I need to start it at 2, seeing as 1 would mess up the system and I don't want it to be considered a prime. For the loop to have a starting number however, it also needs an ending number which is difficult in this instance as it is hard to generate the largest prime that will be needed prior to the loop working.
Here's the program that I am using right now. Where I have marked X is where I need to somehow put an ending number for the For Loop. I guess it would be much simpler if I let the For Loop be completely open, and simply take out anything that '1' would produce in the loop itself, but this feels like cheating and I want to do it right.
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
for i in range(2,X):
check = 0
if i > 1:
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
print (i)
Thanks for your help!
You can step through an unlimited amount of numbers using a generator object.
Insert the following somewhere near the top of your code:
def infinite_number_generator(initial_value=2):
""" Generates an infinite amount of numbers """
i = initial_value
while True:
yield i
i += 1
What this does is it creates a function for constructing generator objects that "pause" whenever they reach the yield statement to "yield" whatever value is specified by the yield command, and then continue to execute from the next line beneath the yield statement.
Python's own range function is itself an example of a generator, and is roughly equivalent to (ignoring the step argument and other peculiarities)
def range(start, end):
i = start
while i < end:
yield i
i += 1
So your program would then look like this:
def infinite_number_generator(initial_value=2):
""" Generates an infinite amount of numbers """
i = initial_value
while True:
yield i
i += 1
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
for i in infinite_number_generator():
check = 0
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
print (i)
if i == limit:
break
I should also point out that the code you provided is buggy - it will never stop printing because there's no checking whether you've found your limit number of primes yet or not.
This should do what you want.
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
counter = 0
i = 2
while counter < limit:
check = 0
if i > 1:
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
counter += 1
print (i)
i += 1
In your code you start i with 2 and always increment by 1, so the i will always remain greater than 1, therefore the test if i > 1 is useless.
For efficiency you can stop the check at the square of i or i/2 (no divisors in [i/2 + 1, i[ ).
you can update your code as follow:
n = int(input("Enter the amount of Prime Numbers: "))
FoundPrimes = 0
i = 2
while FoundPrimes < n:
isPrime = True
for j in range(2,1 + i//2):
if (i % j) == 0:
isPrime = False
if isPrime:
FoundPrimes += 1
print(i, end = '\t')
i += 1

Function to check whether a number is a Fibonacci number or not?

I've made a program which takes number of test cases as input and for each test case, it needs a number as input. Finally it checks whether the numbers you have entered are fibonacci numbers or not and prints accordingly. I've had no problems running it on my PC.But when i upload it to CodeChef.com(where i saw this quesion), it shows runtime error.
Any help is appreciated and as i'm a noob my code might look lengthy ., any modifications are welcome.Thanks!
Here's my code:
def isperfect(n):
import math
if n < 0:
print("No Solution")
return False
else:
test = int(math.sqrt(n))
return test*test == n
test_cases = int(input())
count = 0
store = []
while count < test_cases:
x = int(input())
store.append(x)
count += 1
for each_item in store:
assert isinstance(each_item, int)
s1 = 5*each_item*each_item-4
s2 = 5*each_item*each_item+4
if(isperfect(s1) == True or isperfect(s2) == True):
print("YES")
else:
print("NO")
This is the most elegant solution i've encountered:
def is_fibonacci(n):
phi = 0.5 + 0.5 * math.sqrt(5.0)
a = phi * n
return n == 0 or abs(round(a) - a) < 1.0 / n
The code is not mine, was posted by #sven-marnach.
The original post:
check-input-that-belong-to-fibonacci-numbers-in-python
The runtime error is apparently due to an exception, but Codechef does not provide any more information. It could be various things including divide by zero, memory exhaustion, assertion failure, ...
Although your program works for many common numbers, it doesn't handle all the inputs that the Codechef constraints allow. In particular, the number to be tested can have up to 1000 digits in it. If you try a large input like a 1000-digit number, you'll find it fails. First it fails because of your assert isinstance(each_item, int); a number of 12 digits or more is not of type int. You can just remove the assertion. The next failure occurs because you are using the floating point sqrt routine, and that requires the integer to be converted into floating point. Python can handle very long integers, but the floating point representation is more limited in its precision, and cannot handle 1000 digit integer conversions. That's harder to fix, but can be done. See this ActiveState recipe for an all-integer solution for square root.
I've figured that this can be done by using Newton- Raphson method, i have replaced the code in the function isperfect() with Newton-Raphson formula code, removed assertion and it worked. Thanks for all your help.
Here's the final code:
def isperfect(n):
x = n
y = (x + n // x) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x*x == n
test_cases = int(input())
count = 0
store = []
while count < test_cases:
x = int(input())
store.append(x)
count += 1
for each_item in store:
s1 = 5*each_item*each_item-4
s2 = 5*each_item*each_item+4
if(isperfect(s1) == True or isperfect(s2) == True):
print("YES")
else:
print("NO")
This is going to be a very efficient way of doing it.
In [65]:
import scipy.optimize as so
from numpy import *
In [66]:
def fib(n):
s5=sqrt(5.)
return sqrt(0.2)*(((1+s5)/2.)**n-((1-s5)/2.)**n)
def apx_fib(n):
s5=sqrt(5.)
return sqrt(0.2)*(0.5*(1+s5))**n
def solve_fib(f):
_f=lambda x, y: (apx_fib(x)-y)**2
return so.fmin_slsqp(_f,0., args=(f,),iprint=0)
def test_fib(fibn):
if fibn<1:
print 'No, it is not'
else:
n=int(round(solve_fib(fibn)))
if int(round(fib(n)))==int(fibn):
print 'Yes, it is. (%d)'%n
else:
print 'No, it is not'
In [67]:
asarray(fib(arange(1,20)), dtype='int64')
Out[67]:
array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89,
144, 233, 377, 610, 987, 1597, 2584, 4181])
In [68]:
test_fib(34)
Yes, it is. (9)
In [69]:
test_fib(4181)
Yes, it is. (19)
In [70]:
test_fib(4444)
No, it is not
Fairly simple and efficient way of doing it
def isInFib(n):
if n == 0: return False
elif n == 1: return True
else:
A = 1
B = 1
FLIP = True
while(True):
new = A + B
if new > n: return False
elif new == n: return True
else:
if(FLIP):
A = new
FLIP = not FLIP
else:
B = new
FLIP = not FLIP
Explanation of Algorithm
I first check if my input is equal to 0 or 1, and return appropriate.
If my input is greater than 1, we go into the else, infinite loop.
A and B represent the last two previous numbers in the sequence. We add A and B to get new, the current Fibonacci number.
We check if new is equal to our input number, if that's true we return true, we are done and complete the function.
If it's greater, that means our number is not in the Fibonacci sequence, since we have surpassed it.
if it's less, we need to keep going! and this is where I think it get's confusing to explain. I want to set up A or B as my current fibonacci sequence number (new), but I have make sure that I keep switching between them, since I don't want one to get left behind. Fibonacci sequence takes the previous 2 numbers and adds them together. I want A and B to be my last two previous sums.
I'll use an example
1,1,2,3,5,8,13
A and B are initially 1. So new is equal to 2 first. I then check if I'm over my input number or equal to it. But if my input number is less. I want to keep going.
I want A to equal new (value = 2) then, before we get to our next iteration of the while loop. So that new will equal 2 + 1 as A + B on the next iteration.
But, then THE next iteration of the loop, I want to set B as 3, and I want to leave A being equal to 2. So I have to keep switching between putting the current fibonacci number I'm at, in A or B. And that's why I have the flip logic! It just keeps switching between True and False.
Try this function:
def isfib(number):
num1 = 1
num2 = 1
while True:
if num2 <= number:
if num2 == number:
return True
else:
tempnum = num2
num2 += num1
num1 = tempnum
else:
return False
Here's how it works:
Set num1 and num2 to 0.
If num2 isn't less than or equal to the number return False.
If num2 is equal to the number return True.
Set add num1 to num2, set num1 to num2's original value and go back to step 2.
num=int(input("Enter a number : "))
n1=0
n2=1
i=1
lst=[]
lst.append(n1)
lst.append(n2)
while i<num-1:
n3=n1+n2
n1=n2
n2=n3
lst.append(n3)
i=i+1
for i in lst:
if (num == i):
print("Fibonacci number")
break
else:
print("Not fibonacci")
def isfib(number):
num1 = 0
num2 = 1
while True:
if num2 <= number:
if num2 == number:
return True
else:
tempnum = num2
num2 += num1
num1 = tempnum
else:
return False
n=int(input())
number=n
fibonacci=isfib(number)
if (fibonacci):
print("true")
elif n==0:
print("true")
else:
print("false")

Categories