I'm trying to troubleshoot my implementation of an Infinite Series algorithm to calculate the perimeter of an ellipse. I'm sorry I don't have the expertise to express it in, what appears to be a specialized language this site uses to make it more readable but I'm confident you'll recognize what I'm trying to do.
h = (a − b)^2/(a + b)^2
pi(a+b) (1 + (1/4)h + (1/64)h^2 + (1/256)h^3 + ...)
The site I got this formula from has a calculator but it doesn't show it's work. My results don't match it's results but I don't see where I'm going wrong. I've left out the final multiplication by pi since the error is clearly prior to that point. It's result 40.63874136 after division by pi = 12.93571313 which is quite far from my 14.9879.
Honestly, I don't need someone to understand the language and fix my algorithm. This language is esoteric. A comment along the lines of "your h value should be..." or "Your B,C and HI values look OK but your P values should read: nnn1,nnn2,nnn3" should help me find and fix the problem.
function EllipseEffectiveDiameter(rx=10,ry=1,i=5) =
assert(rx>=0)
assert(ry>=0)
assert(i%1==0&&i>=1)
let(d = rx-ry ,
s = rx+ry ,
h = d^2/s^2,
m = _InfiniteSum(h=h,i=i,s=0),
a = s*m) echo(d=d,s=s,h=h,m=m,a=a)
a;
//ECHO: d = 9, s = 11, h = 0.669421, m = 1.36254, a = 14.9879
function _InfiniteSumPart(h,i,s) =
let(B = BinomialCoefficient(m=1/2,k=i),
C = B^2,
HI= h^i,
P = C*HI,
A = s+P) echo(h=h,i=i,s=s,B=B,C=C,HI=HI,P=P,A=A)
i==0?A:A+_InfiniteSumPart(h,i=i-1,s=A);
//ECHO: h = 0.669421, i = 5, s = 0 , B = 0.0273438 , C = 0.000747681, HI = 0.134431, P = 0.000100511, A = 0.000100511
//ECHO: h = 0.669421, i = 4, s = 0.000100511, B = -0.0390625, C = 0.00152588 , HI = 0.200816, P = 0.000306421, A = 0.000406932
//ECHO: h = 0.669421, i = 3, s = 0.000406932, B = 0.0625 , C = 0.00390625 , HI = 0.299985, P = 0.00117181 , A = 0.00157875
//ECHO: h = 0.669421, i = 2, s = 0.00157875 , B = -0.125 , C = 0.015625 , HI = 0.448125, P = 0.00700196 , A = 0.0085807
//ECHO: h = 0.669421, i = 1, s = 0.0085807 , B = 0.5 , C = 0.25 , HI = 0.669421, P = 0.167355 , A = 0.175936
//ECHO: h = 0.669421, i = 0, s = 0.175936 , B = 1 , C = 1 , HI = 1 , P = 1 , A = 1.17594
Note: I'm only including this for completeness. Several sites use my exact values as examples where their work is shown so I'm fairly confident the problem isn't down here. It's results are column B above.
function BinomialCoefficient(m=1/2,k=1) =
assert(k%1==0 && k>=0)
k==0?1:_BinomialCoefficient(m=m,k=k,i=0,PM=1,PK=1);
function _BinomialCoefficient(m,k,i,PM,PK) =
let(IM = m-i,
IK = i+1,
NM = PM*IM,
NK = PK*IK,
A = NM/NK) //echo(m=m,k=k,i=i,PM=PM,PK=PK,IM=IM,IK=IK,NM=NM,NK=NK,A=A)
k==1?A:_BinomialCoefficient(m=m,k=k-1,i=IK,PM=NM,PK=NK);
UPDATE:
It might be that reading the language is only straightforward if you are accustomed to declarative languages. The most starkly un-nerving thing about declaratives is that variable values can't change. Therefore loops are often done with recursion which I use in both _InfiniteSumPart and _BinomialCoefficient.
The operators allowed in a value or result formula are the basic ones typical of languages like C. If decisions are required, the "bool?true:false" syntax is available and I use this to decide when to recurs or stop.
When it comes to the infinite sum part, being sums, I didn't think it really mattered in what order I computed the terms so I counted down rather than counting up. This should amount (if $i=2$ were used) to ${1h^2}/64 + 1h/4 + 1$ rather than $1 + 1h/4 + 1h^2/64$. Although this could make the running (P)roduct and (A)nswer columns differ from initial expectations, hopefully it isn't directly causing the problem.
