How to find index of a given Fibonacci number - python

I tried to use the following formula
to find the index of a fibonacci number() in a programming question and all the smaller test cases passed but some cases in which F was close to 10^18 failed. I did some dry-run and found out that if F = 99194853094755497 (82nd Fibonacci number) the value of n according to the above formula is 81. I coded this in Python and C++ which can be found here and here respectively. I want to know whether the formula works for every value of F or has some limitations?
Note: After doing some more tests, I found out that the code is giving correct answers till 52nd fibonacci number.
Update: The question has t test cases that's why I used a for loop. The given number F might not necessarily be a Fibonacci number. For ex- If F = 6, then it lies between two fibonacci numbers 5 and 8. Now the index of '5' in the fibonacci sequence is 4 so the answer is 4.

The formula works just fine:
import math
n = 99194853094755497
print math.log(n * math.sqrt(5) + 0.5) / math.log(1.61803398875) - 1
Output:
82.0
A remark on your code:
Using int(...) for rounding off to an integer might cause trouble if the floating point result is very close to 82.0. Numerical issues might cause it to be slightly larger, even though mathematically it would be smaller.

I think your formula is causing a stack overflow because the number is too large to hold in int.

F = 99194853094755497 is 84 Fibonacci number and hence the index for it is 83. Use the below script to get the correct index (integer instead of float).
eps = 10**-10
phi = (1+math.sqrt(5))/2 # golden search ratio
fibonacci_index = int(round(math.log(n * math.sqrt(5)+eps)/math.log(phi)))
Additional Info, code
See this https://github.com/gvavvari/Python/tree/master/Fibonacci_index for more detailed documentation on the implementation

Related

Pascal's triangle expression not resulting in correct output

I am looking for help with some code I have written for Project Euler Problem 148.
The problem is as follows:
Find the number of entries which are not divisible by 7 in the first one billion rows of Pascal's triangle.
I am aware that this specific method will not work as it will - when ran with 1000000000 - result in an overflow error.
Regardless, I am curious why this code does not work:
I use the expression ((math.factorial(r))/((math.factorial(t))*(math.factorial((r-t))))) to find the value of the term at the given row and term, as shown by the formula:
When numrows == 7, the script should print 0, which it does.
When numrows == 100, the script should print 2361, but my code prints 3139.
The code is as follows:
import math
numrows = 100
count = 0
for r in range(numrows):
for t in range(r):
if not (((math.factorial(r))/((math.factorial(t))*(math.factorial((r-t))))) % 7 == 0):
count += 1
print(count)
You incorrectly implemented the formula, using float division / instead of integer division '//'. With the change to
if not math.factorial(r)//(math.factorial(t)*math.factorial(r-t)) % 7 == 0:
You get the output 2261. (Yes, I removed the superfluous parentheses.)
With small numbers, you get exact results in floating-point arithmetic, so your modulus operation yields the desired result. However, when you get up to the lower rows, you run into the limits of floating-point precision -- the result of the division won't be exactly blahblah.0, and your == 0 comparison fails. Thus, you count quite a few cells that aren't supposed to match your criterion.
Finally, add Thierry's repair:
for t in range(r+1):
... and you get 2361, as desired.
Note that this nested loop will not solve the problem in reasonable time. You need to attack this with an analysis of divisibility: how many factors of 7 do you have in the numerator and denominator? If the numerator has more, then the result is divisible by 7.
Use the truncated quotient of r / 7^n for n from 1 to r log 7. Do the same for t and t-r. You can also adjust a running count of 7s as you iterate over the needed values.

Python Binary Search (Maximum number of iterations)

I was googling binary search in python and I found this:
http://openbookproject.net/thinkcs/python/english3e/list_algorithms.html
It said that the general relationship between the max. numbers of iterations (same as Probe right?) and N (size of list) is given by N = 2^k -1, where k is the max number of iterations .
However from my understanding, shouldn't the general relationship be N = 2^k
As each time after a search, we would divide out list by 2, until we get to 1.
Therefore the maximum number of iterations is log2 N instead of log2 (N+1)
I have googled this and I found one website support my answer but without much explanation.
(link here: http://codingexplained.com/coding/theory/binary-search-algorithm)
Could someone explains the math behind it? Thanks.
Let P(n) be the number of probes needed for n elements. Then we can write the following equation:
P(0) = 0
P(n) = 1 + P((n-1)/2)
Explanation:
First we have no elements - nothing to do.
Then we do 1 probe and we're left with (n-1)/2 elements (we throw 1 away because we just checked it) so we need to do P((n-1)/2) more.
The result for P(n) from this equation will be floor(lg(n+1)). You can check it on some examples (like n=6 and n=7) or you can read on how to solve recursive equations

python strange result using math.fmod()

I am playing around with the math module in Python 3.4 and I got some curious results when using fmod function for which I am having hard times in getting detailed info from the python website.
One simple example is the following:
from math import *
x = 99809175801648148531
y = 6.5169020832937505
sqrt(x)-cos(x)**fmod(x, y)*log10(x)
it returns:
(9990454237.014296+8.722374238018135j)
How to interpret this result? What is j?
Is it an imaginary number like i?
If so, why j and not i?
Any info, as well as links to some resources about fmod are very welcome.
The result you got was a complex number because you exponentiated a negative number. i and j are just notational choices to represent the imaginary number unit, i being used in mathematics more and j being used in engineering more. You can see in the docs that Python has chosen to use j:
https://docs.python.org/2/library/cmath.html#conversions-to-and-from-polar-coordinates
Here, j is the same as i, the square root of -1. It is a convention commonly used in engineering, where i is used to denote electrical current.
The reason complex numbers arise in your case is that you're raising a negative number to a fractional power. See How do you compute negative numbers to fractional powers? for further discussion.
cos(x) is a negative number. When you raise a negative number to a non-integral power, it is not surprising to get a complex result. Most roots of negative numbers are complex.
>>> x = 99809175801648148531
>>> y = 6.5169020832937505
>>> cos(x)
-0.7962325418899466
>>> fmod(x,y)
3.3940870272073056
>>> cos(x)**fmod(x,y)
(-0.1507219382442201-0.436136801343955j)
Imaginary numbers can be represented with either an 'i' or a 'j'. I believe the reasons are historical. Mathematicians prefered 'i' for imaginary. Electrical engineers didn't want to get an imaginary 'i' confused with an 'i' for current, so they used 'j'. Now, both are used.

Solving recursive sequence

Lately I've been solving some challenges from Google Foobar for fun, and now I've been stuck in one of them for more than 4 days. It is about a recursive function defined as follows:
R(0) = 1
R(1) = 1
R(2) = 2
R(2n) = R(n) + R(n + 1) + n (for n > 1)
R(2n + 1) = R(n - 1) + R(n) + 1 (for n >= 1)
The challenge is writing a function answer(str_S) where str_S is a base-10 string representation of an integer S, which returns the largest n such that R(n) = S. If there is no such n, return "None". Also, S will be a positive integer no greater than 10^25.
I have investigated a lot about recursive functions and about solving recurrence relations, but with no luck. I outputted the first 500 numbers and I found no relation with each one whatsoever. I used the following code, which uses recursion, so it gets really slow when numbers start getting big.
def getNumberOfZombits(time):
if time == 0 or time == 1:
return 1
elif time == 2:
return 2
else:
if time % 2 == 0:
newTime = time/2
return getNumberOfZombits(newTime) + getNumberOfZombits(newTime+1) + newTime
else:
newTime = time/2 # integer, so rounds down
return getNumberOfZombits(newTime-1) + getNumberOfZombits(newTime) + 1
The challenge also included some test cases so, here they are:
Test cases
==========
Inputs:
(string) str_S = "7"
Output:
(string) "4"
Inputs:
(string) str_S = "100"
Output:
(string) "None"
I don't know if I need to solve the recurrence relation to anything simpler, but as there is one for even and one for odd numbers, I find it really hard to do (I haven't learned about it in school yet, so everything I know about this subject is from internet articles).
So, any help at all guiding me to finish this challenge will be welcome :)
Instead of trying to simplify this function mathematically, I simplified the algorithm in Python. As suggested by #LambdaFairy, I implemented memoization in the getNumberOfZombits(time) function. This optimization sped up the function a lot.
Then, I passed to the next step, of trying to see what was the input to that number of rabbits. I had analyzed the function before, by watching its plot, and I knew the even numbers got higher outputs first and only after some time the odd numbers got to the same level. As we want the highest input for that output, I first needed to search in the even numbers and then in the odd numbers.
As you can see, the odd numbers take always more time than the even to reach the same output.
The problem is that we could not search for the numbers increasing 1 each time (it was too slow). What I did to solve that was to implement a binary search-like algorithm. First, I would search the even numbers (with the binary search like algorithm) until I found one answer or I had no more numbers to search. Then, I did the same to the odd numbers (again, with the binary search like algorithm) and if an answer was found, I replaced whatever I had before with it (as it was necessarily bigger than the previous answer).
I have the source code I used to solve this, so if anyone needs it I don't mind sharing it :)
The key to solving this puzzle was using a binary search.
As you can see from the sequence generators, they rely on a roughly n/2 recursion, so calculating R(N) takes about 2*log2(N) recursive calls; and of course you need to do it for both the odd and the even.
Thats not too bad, but you need to figure out where to search for the N which will give you the input. To do this, I first implemented a search for upper and lower bounds for N. I walked up N by powers of 2, until I had N and 2N that formed the lower and upper bounds respectively for each sequence (odd and even).
With these bounds, I could then do a binary search between them to quickly find the value of N, or its non-existence.

Python thinks Euler has identity issues (cmath returning funky results)

My code:
import math
import cmath
print "E^ln(-1)", cmath.exp(cmath.log(-1))
What it prints:
E^ln(-1) (-1+1.2246467991473532E-16j)
What it should print:
-1
(For Reference, Google checking my calculation)
According to the documentation at python.org cmath.exp(x) returns e^(x), and cmath.log(x) returns ln (x), so unless I'm missing a semicolon or something , this is a pretty straightforward three line program.
When I test cmath.log(-1) it returns πi (technically 3.141592653589793j). Which is right. Euler's identity says e^(πi) = -1, yet Python says when I raise e^(πi), I get some kind of crazy talk (specifically -1+1.2246467991473532E-16j).
Why does Python hate me, and how do I appease it?
Is there a library to include to make it do math right, or a sacrifice I have to offer to van Rossum? Is this some kind of floating point precision issue perhaps?
The big problem I'm having is that the precision is off enough to have other values appear closer to 0 than actual zero in the final function (not shown), so boolean tests are worthless (i.e. if(x==0)) and so are local minimums, etc...
For example, in an iteration below:
X = 2 Y= (-2-1.4708141202500006E-15j)
X = 3 Y= -2.449293598294706E-15j
X = 4 Y= -2.204364238465236E-15j
X = 5 Y= -2.204364238465236E-15j
X = 6 Y= (-2-6.123233995736765E-16j)
X = 7 Y= -2.449293598294706E-15j
3 & 7 are both actually equal to zero, yet they appear to have the largest imaginary parts of the bunch, and 4 and 5 don't have their real parts at all.
Sorry for the tone. Very frustrated.
As you've already demonstrated, cmath.log(-1) doesn't return exactly i*pi. Of course, returning pi exactly is impossible as pi is an irrational number...
Now you raise e to the power of something that isn't exactly i*pi and you expect to get exactly -1. However, if cmath returned that, you would be getting an incorrect result. (After all, exp(i*pi+epsilon) shouldn't equal -1 -- Euler doesn't make that claim!).
For what it's worth, the result is very close to what you expect -- the real part is -1 with an imaginary part close to floating point precision.
It appears to be a rounding issue. While -1+1.22460635382e-16j is not a correct value, 1.22460635382e-16j is pretty close to zero. I don't know how you could fix this but a quick and dirty way could be rounding the number to a certain number of digits after the dot ( 14 maybe ? ).
Anything less than 10^-15 is normally zero. Computer calculations have a certain error that is often in that range. Floating point representations are representations, not exact values.
The problem is inherent to representing irrational numbers (like π) in finite space as floating points.
The best you can do is filter your result and set it to zero if its value is within a given range.
>>> tolerance = 1e-15
>>> def clean_complex(c):
... real,imag = c.real, c.imag
... if -tolerance < real < tolerance:
... real = 0
... if -tolerance < imag < tolerance:
... imag = 0
... return complex(real,imag)
...
>>> clean_complex( cmath.exp(cmath.log(-1)) )
(-1+0j)

Categories

Resources