/// <summary>Computes the Natural Logarithm (Log to base E, or Ln(x)) of the specified argument</summary> public static BigNum Log(BigNum x) { BigNumFactory f = x.Factory; if (x <= f.Zero) { throw new ArgumentOutOfRangeException("x", "Must be a positive real number"); } const int iterations = 25; BigNum one = f.Unity; BigNum two = f.Create(2); // ln(z) == 2 * Sum(n=0;n<inf;n++) { (1 / (2n+1) ) * Pow( (z-1)/(z+1), 2n+1) } BigNum ret = f.Zero; for (int n = 0; n < iterations; n++) { int denom = 2 * n + 1; Double coefficient = 1 / denom; BigNum otherHalf = Pow((x - one) / (x + one), denom); // hurrah for integer powers BigNum sumThis = f.Create(coefficient) * otherHalf; ret += sumThis; } return(ret); }
///////////////////////////////////////// public static BigNum Gamma(BigNum z) { // http://www.rskey.org/gamma.htm // n! = nn√2πn exp(1/[12n + 2/(5n + 53/42n)] – n)(1 + O(n–8)) // which requires the exponential function, and some function O (which the webpage fails to define, hmmm) // so here's the infinite product series from Wikipedia instead // Gamma(z) == (1/z) * Prod(n=1;n<inf;n++) { (1+1/n)^z / (1+z/n) } const Int32 iterations = 25; BigNumFactory f = z.Factory; BigNum ret = z.Power(-1); for (int n = 1; n < iterations; n++) { Double numerator1 = 1 + (1 / n); BigNum numerator2 = Pow(f.Create(numerator1), z); BigNum denominato = f.Unity + z / f.Create(n); BigNum prodThis = numerator2 / denominato; ret *= prodThis; } return(ret); }
public static BigNum Sin(BigNum theta) { BigNumFactory f = theta.Factory; // calculate sine using the taylor series, the infinite sum of x^r/r! but to n iterations BigNum retVal = f.Zero; // first, reduce this to between 0 and 2Pi if (theta > f.TwoPi || theta < f.Zero) { theta = theta % f.TwoPi; } Boolean subtract = false; // using bignums for sine computation is too heavy. It's faster (and just as accurate) to use Doubles #if DoubleTrig Double thetaDbl = Double.Parse(theta.ToString(), Cult.InvariantCulture); for (Int32 r = 0; r < 20; r++) // 20 iterations is enough, any more just yields inaccurate less-significant digits { Double xPowerR = Math.Pow(thetaDbl, 2 * r + 1); Double factori = BigMath.Factorial((double)(2 * r + 1)); Double element = xPowerR / factori; Double addThis = subtract ? -element : element; BigNum addThisBig = f.Create(addThis); retVal += addThisBig; subtract = !subtract; } #else for (Int32 r = 0; r < _iterations; r++) { BigNum xPowerR = theta.Power(2 * r + 1); BigNum factori = Factorial(2 * r + 1); BigNum element = xPowerR / factori; retVal += subtract ? -element : element; subtract = !subtract; } #endif // TODO: This calculation generates useless and inaccurate trailing digits that must be truncated // so truncate them, when I figure out how many digits can be removed retVal.Truncate(10); return(retVal); }
public Expression(String expression, BigNumFactory factory) { _factory = factory; _expression = expression; }