Celé jsem to skoro opravil:
// 10^11 seems to be the maximum too high a figure for the base introduces errors
Base = Math.pow(10, 11);
// num digits in each array item
CellSize = Math.floor(Math.log(Base) / Math.LN10);
MaxDiv = Math.floor(Math.sqrt(Number.MAX_VALUE));
function MakeArray(n, aX, Integer)
{
for(i = 1; i < n; i++)
aX[i] = null;
aX[0] = Integer;
}
function IsEmpty(aX)
{
for(i = 0; i < aX.length; i++)
if(aX[i])return = false;
return true;
}
function Add(n, aX,aY)
{
carry = 0;
for(i = n - 1; i >= 0; i--)
{
aX[i] += Number(aY[i]) + Number(carry);
if(aX[i] < Base)
carry = 0;
else
{
carry = 1;
aX[i] =Number(aX[i]) - Number(Base);
}
}
}
function Subtract(n, aX,aY)
{
for(i = n - 1; i >= 0; i--)
{
aX[i] -= aY[i];
if(aX[i] < 0 && i > 0)
{
aX[i] += Base;
aX[i - 1]--;
}
}
}
function Multiply(n, aX, iMultiplyt)
{
carry = 0;
for(i = n - 1; i >= 0; i--)
{
prod = aX[i] * iMultiplyt + carry;
if (prod >= Base)
{
carry = Math.floor(prod / Base);
prod -= (carry * Base);
}
else
carry = 0;
aX[i] = prod;
}
}
function Divide(n, aX, iDiv, aY)
{
carry = 0;
for (i = 0; i < n; i++)
{
// add any previous carry
currVal = Number(aX[i]) + Number(carry * Base);
theDiv = Math.floor(currVal / iDiv);
// find next carry
carry = currVal - theDiv * iDiv;
// put the result of division in the current slot
aY[i] = theDiv;
}
}
function Arctan(iAng, n, aX)
{
iAng_squared = iAng * iAng;
k = 3; // k is the coefficienticient in the series 2n-1, 3,5..
MakeArray(n, aX, 0); // aX is aArctan
MakeArray(n, aAngle, 1);
Divide(n, aAngle, iAng, aAngle); // aAngle = 1/iAng, eg 1/5
Add(n, aX, aAngle); // aX = aAngle or long angle
for(sign = false; !IsEmpty(aAngle); sign = !sign)
{
Divide(n, aAngle, iAng_squared, aAngle); // aAngle=aAngle/iAng_squared, iAng_squared is iAng*iAng
Divide(n, aAngle, k, aDivK); // aDivK = aAngle/k
if(sign)
Add(n, aX, aDivK); // aX = aX+aDivK
else
Subtract(n, aX, aDivK); // aX = aX-aDivK
k += 2;
}
}
function CalculatePi(numDec)
{
numDec += 5;
iAng = new Array(10);
coefficient = new Array(10);
arrayLength = Math.ceil(1 + numDec / CellSize);
aPi = new Array(arrayLength);
aArctan = new Array(arrayLength);
aAngle = new Array(arrayLength);
aDivK = new Array(arrayLength);
MakeArray(arrayLength, aPi, 0);
MakeArray(arrayLength, aAngle, 0);
MakeArray(arrayLength, aDivK, 0);
// Pi/4 = 4*Arctan(1/5)-Arctan(1/239)
// the last item is 0!
coefficient[0] = 4;
coefficient[1] = -1;
coefficient[2] = 0;
// iAng holds the angles, 5 for 1/5, etc
iAng[0] = 5;
iAng[1] = 239;
iAng[2] = 0;
for(i = 0; coefficient[i] != 0; i++)
{
Arctan(iAng[i], arrayLength, aArctan);
Multiply(arrayLength, aArctan, Math.abs(coefficient[i]));
if(coefficient[i] > 0)
Add(arrayLength, aPi, aArctan);
else
Subtract(arrayLength, aPi, aArctan);
}
// we have calculated Pi/4, so need to finally Multiplytiply
Multiply(arrayLength, aPi, 4);
output = "";
for(i = 0; i <= numDec; i++)
output += String(aPi[i]).charAt(i);
return output;
}
Abych zjistil, že to dělá co mých 5 řádků? Ne - opravdu mi nenacpeš, že tahle spatlanina v JS je lepší, než můj postup... Nehledě na fakt, jak špatně je ten kód napsaný, i sebelepší kód v JS by se C# nevyrovnal... (Už jen proto, že má .NET CIL, zásobu optimalizovaných knihoven,...)
Jak se vůbec můžete ohánět výkonem, efektivitou atp. Když mi radíte daleko horší postupy? :D