This question already has answers here:
How does the fibonacci recursive function "work"?
(12 answers)
Closed 2 years ago.
# Function for nth Fibonacci number
def Fibonacci(n):
if n<0:
print("Incorrect input")
# First Fibonacci number is 0
elif n==1:
return 0
# Second Fibonacci number is 1
elif n==2:
return 1
else:
return Fibonacci(n-1)+Fibonacci(n-2)
# Driver Program
print(Fibonacci(9))
I am new to programming.
I cant get how this codes finds out the Fibonacci number....
How does the program calculates the value of (n-1) and (n-2)
Your program uses recursion.
Here you can find visualization, which could help you with understanding:
https://observablehq.com/#victormutai/visualizing-recursive-fibonacci-algorithm
Alternative implementation is iterative algorithm. I could be easier to understand
def f(n):
a, b = 0, 1
for i in range(0, n):
a, b = b, a + b
return a
Here is an illustratory diagram from the SICP book.
When Fibonacci(5) is invoked, Fibonacci(5-1) (fib 4) and Fibonacci(5-2) (fib 3) are invoked in return. When Fibonacci(4) is invoked, Fibonacci(4-1) and Fibonacci(4-2) are invoked in return, so on and so forth. This is called a recursion.
Finally, when either Fibonacci(2) or Fibonacci(1) is invoked, its result 1 and 0 is returned directly without further invocation. It is the termination conditions of such recursion.
By the way, as is depicted in the diagram, the multiple times' invocations of fib 3, which is seen as repeated calculation, result in inefficiency. So it is only for demonstrating how recursion works while usually not used to calculate fibs in practice.
return Fibonacci(n-1)+Fibonacci(n-2)
This is a recursion. You should cache values to reduce recalculation.
moreover, there is Binet's formula to calculate it at O(1) time.
https://en.wikipedia.org/wiki/Fibonacci_number
The idea behind that piece of code is recursion. Have a look at this to find out more about it.
To explain how your code works to identify the nth number in the Fibonacci series, first you need to understand how a Fibonacci series is generated.
0, 1, 1, 2, 3, 5, 8, 13, and so on.
Here if you look at the first two numbers it is 0 and 1, these are the base numbers, from there on the next number is found out by the addition of the previous two numbers. Hence the formula.
F(1) = 0
F(2) = 1
F(n) = F(n-1) + F(n-2)
Now if you look at your code the above is exactly depicted here. Any value of n less that 1 will be considered as invalid. A value of 1 returns a 0 and a value of 2 returns a 1. this is exactly the same as we have mentioned above.
Fibonacci(n-1)+Fibonacci(n-2)
Finally for all other cases we find the previous two numbers in the series by using the same rule(function) and sum them to get the desired number.
Related
This question already has answers here:
Does range() not evaluate its argument every time?
(3 answers)
Closed 3 years ago.
I'm an intro computer science student working in Python 3.7.1.
We were working with "Additorials" where you take a number and take get the sum of the number plus every number before it.
Ie: for the number 10-- 10+1+2+3+4+5+6+7+8+9 = 55
I had to write a program that performed this operation as a function. However, I did it in a way that shouldn't work, but it does.
def bigAdd(n):
for i in range(0,n):
n+=i
return n
for example, if I input the number 10, it returns 55
But... Why?
If the upper limit of this loop is n, and it is constantly being incremented by i, shouldn't it run forever because it is constantly raising its limit? Why does it return any answer, let alone the correct one?
You are adding to n, which initially is 10 (or whichever upper bound you are using). Thus your result is indeed 10 (the initial value) + 0 + 1 + ... + 9 (from the range).
Having said that, I'd still recomment not using the initial value of n and instead getting the sum of range(1, n+1), as that's much clearer.
>>> sum(range(1, n+1))
55
Or if you want to show off:
>>> n*(n+1)//2
55
About your second question:1 No, the range(0, n) is evaluated only once, when the for loop is first entered, not in each iteration. You can think of the code as being roughly2 equivalent to this:
r = range(0, n) # [0, 1, 2, 3, ..., n-2, n-1]
for i in r:
n+=i
In particular, Python's for ... in ... loop is not the "typical" for (initialization; condition; action) loop known from Java, C, and others, but more akin to a "for-each" loop, iterating over each element of a given collections, generator, or other kind of iterable.
1) Which, I now realise, is actually your actual question...
2) Yes, a range does not create a list but a special kind of iterable, that's why I said "roughly".
range(0,n) is evaluated once before the loop is entered.
This isn't like a typical for loop from other languages that has a condition that is constantly checked. range returns a range object that produces numbers, and the upper limit is set when the range object is created. Changing n has no effect on the range object that's already been constructed.
This is because int values are immutable and range captures that particular instance only once at the beginning.
When inside the loop, the variable n which was pointing to the value 10 initially is re-pointing everytime to a new int instance when you are adding some number to it. And since range is evaluated only once it keeps the reference to the original int instance 10.
The int instance which is referenced by the range function at the beginning, is not at all mutated in the for-loop and is still pointing the int instance value of 10.
That is why the loop is completed even though n is now pointing to a different number every time.
Try this example snippet, you can prove this:
def bigAdd(n):
for i in range(0,n):
#temp captures the int before the addition
temp = n
n+=i
print(temp is n)
return n
The output is:
bigAdd(10)
True
False
False
False
False
False
False
False
False
False
Out[8]: 55
The first line prints True as 10 + 0 is 10 so both are the same instance.
As I understand it when you have range(0,n) you define a generator with upper limit 10, because n was 10, and after that the generator doesn't change.
The range() function returns a series of numbers on first instance. In your case, from 0 to n-1. So, if you call bigAdd(10), you'll get numbers from 0 to 9.
The function then increments the originally-input number (in your case, 10) by the sum of all the smaller numbers (in this case, 0 + 1 + ... + 9) which is 45.
So, adding the 45 to the original 10 gives you 55.
The range function is taking a value of n as its upper bound which prevents the for loop from funning forever. The for loop stops when i has the same value as n (which in the example you gave is 10.
So your code
for i in range(0,n):
is the equivalent of saying "first let i have a value of 0, then on the next iteration of the loop, let i have a value of 1, ..... and so on until i has a value of 10".
Well, you can solve this problem in a loop, but why not use the Gaußsche Summenformel (sorry for the German link, I couldn't find the english name of it), which is indeed
n (n+1)
-------
2
Put this in a function and return the value:
def gaussian_sum(n):
return (n * (n+1)) // 2
This question already has answers here:
How does return statement with recursion calls hold intermediate values in Python?
(2 answers)
Closed 5 years ago.
I'm having a bit of trouble understanding a couple of things regarding recursive functions in Python (well, I guess in general). I tried looking for the answer but wasn't sure how to look for it either.
Taking the recursive function example most common when I search:
def sfactorr(j):
if j == 1:
return 1
else:
return j * sfactorr(j-1)
each time the function is greater than 1, it starts again until j == 1. But when it hits 1, shouldn't the return value be 1? Obviously when you run it you get the result of the whole function, but I don't seem to fully understand why that is.
In other words, how come it returns the correct value and not the one the base condition is returning?
Thanks
You have to work through the steps.
Say we pass 3 to the function.
When the function first runs, j > 1. So instead of returning 1, it returns j * [the function called with one less than j). But it can't actually return that until the function it called has returned.
It keeps on doing that until j is 1. That's the base condition. When j is 1, 1 gets returned to the function above it.
So. Starting with j == 3:
(1) j == 3, returning j * the result of (2)
(2) j ==2, returning j * the result of (3)
(3) j == 1, returning 1
So the functions are called in order (1), (2), (3), but return in order (3), (2), (1).
(3) returns 1
(2) takes the 1 from (3) and multiplies it by (2), resulting in 2. Then it returns that.
(1) takes the 2 from (2) and multiplies it by 3, resulting in 6. It returns that as a final value.
Recursive statements mean that the functions all collapse back into themselves, not that only the last statement runs.
I'm receiving a "maximum recursion depth exceeded" error when executing my program to solve this problem. Project Euler's question #5 asks to find:
The smallest positive number that is evenly divisible by all of the numbers from 1 to 10.
I've tried to write a program that recursively checks if x is divisible by each integer 1-10, and if it doesn't then we call it again with x incremented by 1 and repeat until x is found. (In this case the answer is 2520, which is why I added the if statement.)
def euler5(x):
if x < 2521:
for i in range(1, 11):
if x % i == 0:
print(x)
else:
euler5(x+1)
else:
print(x)
x = 2
print(euler5(x))
The reason for this is that Python (or CPython, at least) has a limited stack size and no tail call optimization. So you cannot use unbounded recursion in Python, unlike Scheme (for example).
The solution is to use a regular loop:
x = 0
while True:
x += 1
# Put loop body here
In you defined function, you could you a loop even if you do not know math functions. However, your code is not efficient as program has to keep checking the values to see if it matches the condition. Recursion is not recommended as it should be flexible to be used with other values not just for this question. Euler questions are meant to train your coding practices.
A better method can be used to simplify your code:
from functools import reduce
from fractions import gcd
def lcm(a,b):
return a*b//gcd(a,b) #gcd is greatest common divisor AKA HCF
print (reduce(lcm, range(1, 20+1)))
this was one of the problems I was assigned in MyProgrammingLab. I've attempted to answer this problem over 45 times, but can't get it right.
Any help will be appreciated
Question:
In the following sequence, each number (except the first two) is the sum of the previous two numbers: 0, 1, 1, 2, 3, 5, 8, 13, .... This sequence is known as the Fibonacci sequence.
We speak of the i'th element of the sequence (starting at 0)-- thus the 0th element is 0, the 1st element is 1, the 2nd element is 1, the 3rd element is 2 and so on. Given the positive integer n, associate the nth value of the fibonacci sequence with the variable result. For example, if n is associated with the value 8 then result would be associated with 21.
My work:
def fib(n):
if n <= 1:
result == n
elif n >= 1:
result = fib(n-1)+fib(n-2)
else:
return result
It's because in all of your cases, you assign the result but don't return it.
So, for example, when fib(1) is called, Python returns None because you never told it to return result in that case. The same thing happens for, say, fib(45).
To correct this, just return result always. (This is a good idea no matter what type of program you are writing - functions should always have an explicit return value).
def fib(n):
if n <= 1:
result = n
elif n > 1:
result = fib(n-1)+fib(n-2)
return result # always return result!
Things to Know
You should be aware that this implementation of the Fibonacci sequence is the least efficient one out there. If you can ditch the recursive calls altogether and just use a while loop to calculate fib(n) - or, if you want recursion, store previously computed values of fib(n) instead of forcing it to compute all the way to fib(n) - you will have a much more efficient implementation.
Your code contained numerous issues, such as
Assigning without returning, which we've already discussed.
Using == instead of =. The first checks if the left and right hand side are equal, and returns True or False. The second actually assigns the value of the right hand side to the variable on the left hand side. Don't confuse checking for equality with assignment.
Using the same base case twice but telling Python to do something different in both cases. This is such a bad idea that I feel jonrsharpe in the comments is justified in saying "Seriously?". The reason for this is because doing this makes no sense and makes it hard to predict behaviour. The whole point of an if-else statement is to do different things in different cases.
Edit based on examples provided by OP. Indentation should only be four spaces, not eight. This is more of a stylistic issue than anything else, but it is the standard.
def fib(n):
if n < 2:
return n
else:
return fib(n-1)+fib(n-2)
You can essentially reduce it to this. You could even leave out the else and say:
def fib(n):
if n < 2:
return n
return fib(n-1)+fib(n-2)
but you said you need to have an else-case for whatever reason.
I wrote this one for my assignment. I know it's a little indirect, but it works and that's what's important :)
n = int(input("Insert a number: "))
i = 0
fib_list = [1, 1, 0]
for i in range (0,2):
if n == 0:
result = fib_list[2]
elif n <= 2:
result = fib_list[0]
for i in range (2,n):
result = fib_list[0] + fib_list[1]
fib_list.insert(0, result)
i += 1
result = fib_list[0]
By the way, you don't need to define an input to use in the myprogramminglab question.
I added the input version here because I used it in my tests.
This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 7 years ago.
I am new to Python and I'm attempting to write a code that checks to see whether or not a number is prime. So far, I've written this:
def main():
n = input("Enter number:")
isprime(n)
def isprime():
x = Prime
for m in range (1,n+1,1)
result = n % m
print result
main()
I'm not sure how to proceed after this. I know I have to define isprime. Any help would be greatly appreciated. Thank you!
Your first and biggest problem is that you need to list n as a parameter to isprime before you can use it within isprime, and before you can pass an argument in main. See the tutorial on Defining Functions for more details. But basically, it's like this:
def isprime(n):
Also, that x = Prime is going to raise a NameError, because there's nothing named Prime. Given that it doesn't actually do anything at all, you should just delete it.
Of course that won't make this a complete working prime testing function, but it is how to proceed from where you are.
The next step is to consider what to return from the function. If you find a value that divides n, then obviously n isn't prime, and therefore isprime is false. If you go through all possibilities and don't find anything that divides n, then isprime is true. So, with two return statements in the right places, you can finish the function.
Once it's at least always returning True or False, you have bugs to fix.*
Look at what numbers you get from range(1, n+1, 1). Two of those numbers are guaranteed to divide any n. How do you avoid that problem?
After you've got it working, then you can work on optimizing it. If you look up primality test on Wikipedia, you can see a really simple way to improve the naive trial division test. A bit of research will show the pros and cons of different algorithms. But if what you've got is fast enough for your purposes, it's usually not worth putting more effort into optimizing.
* You might want to consider writing a test program that calls isprime on a bunch of numbers and compares the results with the right answers (for answers you already know off the top of your head—1 is not prime, 2 is prime, 17 is prime, etc.). This is called Test Driven Development, and it's a great way to make sure you've covered all the possible cases—including outliers like 0, 1, 2, -3, etc.
Your isprime is quite close. The first line x = Prime is unnecessary, so let's get rid of that.
Now, let's take a look at what you're doing next:
You seem to want to check if there are any numbers that divide n perfectly. While this is the correct approach, you are including n and 1 in the numbers that you are testing. This is wrong for obvious reasons.
There is another error: you use n without ever defining it (I think you want it to be a parameter to your function). So let's put all this together:
def isprime(n):
for m in range(2, n):
if not n%m: # m divides n perfectly
return False
return True # if n were not prime, the function would have already returned
But going a step further, you don't really have to check every number between 2 and n-1. You just need to check the numbers between 2 and the square-root of n:
def isprime(n):
for m in range(2, int(n**0.5)+1):
if not n%m:
return False
return True