Reputation: 1190
Given a number and a ratio, how do I create an exponentially growing list of numbers, whose sum equals the starting number?
>>> r = (1 + 5 ** 0.5) / 2
>>> l = makeSeq(42, r)
>>> l
[2.5725461188664465, 4.162467057952537, 6.735013176818984,
10.897480234771521, 17.63249341159051]
>>> sum(l)
42.0
>>> l[-1]/l[-2]
1.6180339887498953
>>> r
1.618033988749895
Upvotes: 0
Views: 1877
Reputation: 1190
Based off of Alex Hall's answer, this is what I ended up using:
def geoProgress(n, r=(1 + 5 ** 0.5) / 2, size=5):
""" Creates a Geometric Progression with the Geometric sum of <n>
>>> l = geoProgress(42)
>>> l
[2.5725461188664465, 4.162467057952537, 6.735013176818984,
10.897480234771521, 17.63249341159051]
>>> sum(l)
42.0
>>> l[-1]/l[-2]
1.6180339887498953
"""
return [(n * (1 - r) / (1 - r ** size)) * r ** i for i in range(size)]
Upvotes: 0
Reputation: 36023
A discrete sequence of exponentially growing numbers is called a geometric progression. The sum is called a geometric series. The formula here can easily be solved to produce the sequence you need:
>>> n = 5
>>> r = (1 + 5 ** 0.5) / 2
>>> r
1.618033988749895
>>> total = 2.28
>>> a = total * (1 - r) / (1 - r ** n)
>>> a
0.13965250359560707
>>> sequence = [a * r ** i for i in range(n)]
>>> sequence
[0.13965250359560707, 0.22596249743170915, 0.36561500102731626, 0.5915774984590254, 0.9571924994863418]
>>> sum(sequence)
2.28
>>> sequence[1] / sequence[0]
1.618033988749895
>>> sequence[2] / sequence[1]
1.618033988749895
>>> sequence[2] / sequence[1] == r
True
It's also worth noting that both this problem and the original problem of the Fibonacci could be solved using a binary search / bisection method.
Upvotes: 5
Reputation: 4791
Forget about the decimal numbers, like julienc mentioned program would never know where to start from if you bend the 'definition of Fibonacci series' like the way you wish to. You must be definitive about fibonacci series here.
For whole numbers and actual definition of fibonacci series, best you can do is make a program which takes number as input and tells whether the number sums up to some fibonacci series. And if it does then print the series. Assuming this is what you want.
a = 33
f_list = []
def recur_fibo(n):
if n <= 1:
return n
else:
return(recur_fibo(n-1) + recur_fibo(n-2))
i=0
total = 0
while True:
num = recur_fibo(i)
total += num
f_list.append(num)
if total > a:
print "Number can not generate fibonacci series"
break
elif total == a:
print "Series: %s" % f_list
break
i +=1
Output:
Series: [0, 1, 1, 2, 3, 5, 8, 13]
Upvotes: 0
Reputation: 1674
The Fibonacci sequence goes as follows: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ... etc. As you may have already seen in the comments on your question, the Fibonacci sequence itself doesn't "scale" (i.e., fib_seq * 0.12 = 0, 0.12, 0.12, 0.24, 0.36, 0.60, 0.96 ... etc.
isn't the Fibonacci sequence any longer), so you you can really only make a Fibonacci series in the order the values are presented above. If you would like to make the Fibonacci sequence dynamically scalable depending on some criteria, please specify further what purpose that would serve and what you are having trouble with so that the community can help you more.
Now, let's start with the basics. If you've had trouble with implementing a function to print the Fibonacci Sequence in the first place, refer to the answer @andrea-ambu gives here: https://stackoverflow.com/a/499245/5209610. He provides a very comprehensive explanation of how to not only implement the Fibonacci Sequence in a function in any given language, but even goes further to explore how to do so efficiently!
I presume that you are trying to figure out how to write a function that will take a user-provided integer and print out the Fibonacci series that sums up to that value (i.e., print_fib_series(33)
would print 0 + 1 + 1 + 2 + 3 + 5 + 8 + 13
). This is fairly easily achievable by just incrementally adding the next value in the Fibonacci series until you arrive to the user-provided value (and keeping track of which values you've summed together so far), assuming that the user-provided value is a sum of Fibonacci series values. Here's an easy implementation of what I just described:
# Recursive implementation of the Fibonacci sequence from the answer I linked
def fib_seq(ind):
if ind == 0:
return 0;
elif ind == 1:
return 1;
else:
return fib_seq(ind - 1) + fib_seq(ind - 2);
def list_fib_series(fib_sum, scaling_factor):
output_list = [];
current_sum = 0;
for current_val in fib_seq():
current_sum += current_val * scaling_factor;
output_list.append(current_val);
if current_sum == fib_sum:
return output_list;
elif current_sum > fib_sum:
return 0; # Or you could raise an exception...
fib_list = list_fib_series(2.4, 0.12):
print ' + '.join(map(str, fib_list));
So, considering the decimal value of 2.4 you could apply a linear scaling factor of 0.12 to the Fibonacci series and get the result you indicated in your question. I hope this helps you out!
Upvotes: 2
Reputation: 531055
Pick any sequence of Fibonacci numbers you want. Add them up, and divide your target number by the sum to get a scaling factor. Multiply each number in your chosen sequence by the scaling factor, and you'll have a new sequence that sums to your target, and has the same ratio of adjacent terms as the original sequence of Fibonacci numbers.
To generate the example in your question, note that 1 + 2 + 3 + 5 + 8 = 19, and 2.28/19 = 0.12.
Upvotes: 3