My code which adds fibonacci numbers to a list adds too many terms. - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: My code which adds fibonacci numbers to a list adds too many terms. (/thread-27549.html) |
My code which adds fibonacci numbers to a list adds too many terms. - STBK - Jun-10-2020 Hi, I am new to programming and am self-learning, using projecteuler as a source of questions. I am trying to create a program which generates the fibonacci sequence until the nth term is sufficiently large, and put all the values in a list. My program is as follows: x = [0, 1] for j in x: if j > 100: break else: x.append(x[-1]+x[-2]) print(x) In this example, I want it to print out every Fibonacci number less than 100. However, it always prints two more values after my upper bound: in this case, it adds 89 to the list (which I want), followed by 144 and 233. I am wondering if I have a conceptual misunderstanding of how "for _ in _" statement works, as I would've thought it works as follows: adds first couple of terms fine, then gets to 89, recognises that 89 is less than 100 so adds the next term to the list (144), checks to see if 144 is less than 100, which it isn't, and so does not add 233 to the list. Apologies if this is a simple mistake, as I said I am new to python. Thanks. RE: My code which adds fibonacci numbers to a list adds too many terms. - DeaD_EyE - Jun-10-2020 Use an infinite generator together with itertools.islice .from itertools import islice def fib(): a, b = 0, 1 while True: yield a a, b = a + b, a fibs = list(islice(fib(), 0, 100))The yield in the function turns the function into a generator. Generators: https://realpython.com/introduction-to-python-generators/ Islice: https://docs.python.org/3/library/itertools.html#itertools.islice RE: My code which adds fibonacci numbers to a list adds too many terms. - STBK - Jun-10-2020 (Jun-10-2020, 02:14 PM)DeaD_EyE Wrote: Use an infinite generator together with Hi Dead_EyE, thank you for your response. This is a much nicer way to write out the Fibonnaci numbers compared to how I did it! Even though what you've posted is much nicer, I'd still be interested in knowing why my original code didn't work. Thanks. RE: My code which adds fibonacci numbers to a list adds too many terms. - DPaul - Jun-10-2020 Quote:Even though what you've posted is much nicer, I'd still be interested in knowing why my original code didn't work.That is because you test on j > 100, but j is never the last item. Test on "if x[-1]+x[-2] > 100:", that is the last item. Paul RE: My code which adds fibonacci numbers to a list adds too many terms. - DeaD_EyE - Jun-10-2020 Misunderstanding. You meant to have values in the list which are lower than 100. My example creates a list with exactly 100 elements. You compared j > 100 , which is not the final value.You've to compare (x[-1] + x[-2]) >= 100 .x = [0, 1] for j in x: result = x[-1] + x[-2] if result >= 100: # stop is result is bigger or equal to 100 break x.append(result) print(x)With my provided example: from itertools import takewhile, islice def fib(): a, b = 0, 1 while True: yield a a, b = a + b, a def condition(value): return value < 100 generator = fib() fibs_below_100 = list(takewhile(condition, generator))And you can combine different functions from itertools. Not bigger than 50 and maximum 10 elements: fib_gen = fib() fibs_below_50 = takewhile(lambda x: x < 100, fib_gen) fibs_max_10_elements = islice(fibs_below_50 , 0, 10) final_result = list(fibs_max_10_elements)There is one big pitfall, if you use infinite generators: [x for x in fib if x < 100]This code will run until you get a MemoryError or hit CTRL+C. There is no stop condition. Only the decision is made to take x or not. RE: My code which adds fibonacci numbers to a list adds too many terms. - STBK - Jun-10-2020 (Jun-10-2020, 02:54 PM)DPaul Wrote: Misunderstanding. You meant to have values in the list which are lower than 100. Hi, this explanation and the code you have shown me is extremely helpful and I am very grateful. I find the example using "result = x[-1] + x[-2]" especially intuitive. I just have one final question. Why is j not the final value? Thanks for all your help. RE: My code which adds fibonacci numbers to a list adds too many terms. - deanhystad - Jun-10-2020 The reason you get two extra numbers in the list is because you are testing x[-3] >. You start with two values in x and j never catches up with the end of the list because each time you test the value of j you add a value to x. If you want to stop at or before 100, use the DeaD_Eye's test. If you want to stop after the first value >= 100 (kind of what your original code looks like) just use: x = [0, 1] while x[-1] < 100: x.append(x[-1]+x[-2]) print(x) RE: My code which adds fibonacci numbers to a list adds too many terms. - DPaul - Jun-10-2020 Quote: I just have one final question. Why is j not the final value?I can only explain it the verbose way. You start with "x = [0,1]", then you say "for j in x:" So you start with 0 first, which is not the last one, but you are always adding the true last and one-but-last [-1] and [-2] With the sum you are adding a third item, while the loop now moves to the second one. So by testing j you are always "late". Paul |