コード例 #1
0
        /////////////////////////////////////////

        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);
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
        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);
        }