Perl - 35 bytes
print!map$\-=1/($%+=$.=$%-$.),0..<>
Sample usage:
$ echo 10 | perl inv-fib-sum.pl
3.34170499581934
Further Analysis
It's interesting to note that the sum
is convergent. Supposing we wanted to calculate a few thousand digits or so, the naïve approach is almost sufficient. The convergence is quite slow at first, but speeds up rapidly, so that 1000 digits only takes about 4800 terms. A sample Python implementation might be:
a=[1,1]
for i in range(4800):a=[a[0]+a[1]]+a
z=10**1000
print sum(map(lambda i:z/i,a))
which after a second or so outputs:
33598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142832933
(The last four digits don't quite converge, but we'll ignore that for now.)
Let's try to speed up the convergence a bit. A standard trick is to use Euler's Transform. After expansion and simplification, this produces a nicer result:
It should be fairly apparent why this converges more quickly; each term has 3 terms in the denominator rather than just one. Calculating 1000 digits takes only 1600 (one third as many) terms:
a=[1,1]
for i in range(1601):a=[a[0]+a[1]]+a
z=10**1000
print sum(map(lambda i:(-1)**i*z/(a[i]*a[i+1]*a[i+2]),range(1601)))
Output:
3598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142834500
(Here again, the last 4 digits don't converge.)
We're not quite done yet. If we combine adjacent terms, we end up with the following:
Factoring out each term from the remainder of the summation gives the nested expression:
Now we're getting somewhere. Notice that the numerators of follow OEIS A206351 (with the exception of the first term, which is doubled):
and the denominators follow OEIS A081016 (shifted by one term):
Each of these have very simple recurrence relations, namely:
and
respectively. Putting it all together, we find that we need only 800 iterations for 1000 digits:
b,c=[16,3,1],[273,40,3]
for i in range(800):b,c=[7*b[0]-b[1]-4]+b,[7*c[0]-c[1]-1]+c
s=z=10**1000
for x,y in zip(b,c):s=(z+s)*x/y
print s
which outputs:
3598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142835294
(Here, finally, the last 4 digits converge correctly.)
But that's still not quite everything. If we observe the intermediate values for s, we find that it converges to a different value entirely before converging on the actual convergence point. The reason for this is the following:
Solving for a stable s, we find that:
Because this is a simple root, we can use Newton's Method to get us most of the way there, and then jump in at a much later point in the iteration. Only about 400 digits of precision are necessary (as the b and c values aren't any larger than that anyway), which can be achieved with just 7 iterations, while saving 320 iterations of the main loop:
b,c=[16,3,1],[273,40,3]
for i in range(480):b,c=[7*b[0]-b[1]-4]+b,[7*c[0]-c[1]-1]+c
z=10**1000;s=z/17
for i in range(7):s-=(s*s+s*z-z*z/16)/(2*s+z)
for x,y in zip(b,c):s=(z+s)*x/y
print s
Output is identical to the previous, runtime is about 0.02s on my system using PyPy v2.1. Even though it needs one tenth the number of iterations as the original, it's significantly faster than 10x due to multiplying and dividing by much smaller terms. I don't think much more can be tweaked out of it, although I'd be happy to be shown wrong.
2This is equal (if I've understood it right) to 1/φ (reciprocal of golden ratio). If you want us to actually use the Fibonacci numbers in the calculation, you should specify. If not, there's certainly languages where
φ
is a builtin. (not APL for a change) – marinus – 2014-01-09T22:40:37.093@marinus Changed. – None – 2014-01-09T22:55:45.827
1
@marinus, it's not equal to 1/phi. It does have a closed form, but it's quite tricky. Mathematica probably has a built-in, but I doubt many other languages do.
– Peter Taylor – 2014-01-09T23:22:50.743@OP, "highest accuracy possible" is a useless winning criterion. Anyone who has a language which supports arbitrary decimal precision, or who can be bothered to write the support for it, can make an implementation with a precision parameter and then engage in an edit war to increase that parameter. It would make more sense to ask for a function which takes the precision as a parameter. Judging on speed is also tricky, because it depends on many factors (CPU model, RAM available, system load, ...). – Peter Taylor – 2014-01-09T23:28:44.453
@PeterTaylor Is this better? – None – 2014-01-09T23:41:03.783
That's one way to improve it. You could probably remove the last rule now, because any approach which doesn't require adding the inverses of the numbers themselves is going to be very interesting. – Peter Taylor – 2014-01-09T23:53:48.567
What is the winning criteria? – Justin – 2014-01-10T00:26:08.950
@Quincunx Sorry, it was removed during question modification. – None – 2014-01-10T00:28:24.560
@Quincunx Fixed now. – None – 2014-01-10T00:29:08.783
For comparison, the answer I would have submitted to an earlier version of the question which asked for the constant per se:
import java.math.*;public class C{public static void main(String[]_){MathContext C=new MathContext(110);BigDecimal I=BigDecimal.ONE,a=I,b=I,s=I,S,x,y;int n=11;while(n-->1){b=I.subtract(a);s=a.subtract(b);a=a.pow(2).add(I).divide(s,C);}S=I.divide(b.negate(),C);while(++n<20){x=b.divide(a,C).pow(n);y=x.divide(a,C);S=S.add(I.divide(I.subtract(x),C).add(y.divide(I.subtract(y),C)).multiply(y.pow(n)));}System.out.println(S.multiply(s,C));}}
– Peter Taylor – 2014-01-11T00:15:06.857@PeterTaylor Thank you for helping me. I seem to keep making different blunders. Fortunately, they have been more and more minor (it seems). – None – 2014-01-11T01:29:17.213