示例#1
0
        /// POWER INTEGER
        ///
        /// <summary>
        /// Performs the quick mathematical power operation.
        /// Works only for integer exponent values.
        ///
        /// WARNING! The power value here should be an integer number,
        /// that is, the calculator method 'integerPower(power)' should
        /// return the same value as power. Otherwise, the result
        /// would be unpredictable AND INCORRECT.
        /// </summary>
        /// <param name="number">The number to raise to the power.</param>
        /// <param name="power">The INTEGER exponent of the power.</param>
        /// <returns>The number raised to the integer power.</returns>
        public static T PowerInteger_Generic(T number, T power)
        {
            power = calc.intPart(power);

            if (power == Numeric <T, C> .Zero)
            {
                return(calc.fromInt(1));
            }

            else if (power < Numeric <T, C> .Zero)
            {
                if (number <= Numeric <T, C> .Zero)
                {
                    throw new ArgumentException("Cannot raise a non-positive number to a negative power.");
                }
                return(calc.div(calc.fromInt(1), PowerInteger_Generic(number, calc.negate(power))));
            }

            // Ноль в любой степени будет ноль:

            if (calc.eqv(number, calc.zero))
            {
                return(calc.zero);
            }

            Numeric <T, C> res  = calc.fromInt(1);            // результат возведения в степень
            Numeric <T, C> copy = calc.getCopy(number);       // изменяемая копия (переданное число может быть ссылочным типом)

            T two = calc.fromInt(2);
            T one = calc.fromInt(1);

            while (power > Numeric <T, C> .Zero)
            {
                // Если остаток от деления на 2 равен 1
                if (calc.eqv(WhiteMath <T, C> .Modulus(power, two), one))
                {
                    res *= copy;
                }

                copy *= copy;
                power = calc.intPart(calc.div(power, two));
            }

            return(res);
        }
示例#2
0
        /// <summary>
        /// Finds the greatest common divisor of two integer-like numbers
        /// using the simple Euclid algorithm.
        ///
        /// The calculator for the numbers is recommended to provide reasonable implementation
        /// of the remainder operation (%) - otherwise, the function
        /// Modulus from whiteMath class will be used.
        ///
        /// Will work with floating-point type numbers only if they are integers;
        /// In case of division errors the result will be rounded and thus not guaranteed.
        /// </summary>
        /// <param name="one"></param>
        /// <param name="two"></param>
        /// <returns></returns>
        public static T GreatestCommonDivisor(T one, T two)
        {
            Contract.Requires <ArgumentException>(one != Numeric <T, C> .Zero && two != Numeric <T, C> .Zero, "None of the numbers may be zero.");

            Contract.Ensures(Contract.Result <T>() > Numeric <T, C> .Zero);
            Contract.Ensures((Numeric <T, C>)one % Contract.Result <T>() == Numeric <T, C> .Zero);
            Contract.Ensures((Numeric <T, C>)two % Contract.Result <T>() == Numeric <T, C> .Zero);

            // T может быть ссылочным типом, поэтому необходимо
            // предостеречь объекты от изменения
            // а также отсечь знаки по необходимости

            T oneTmp;
            T twoTmp;

            if (calc.mor(calc.zero, one))
            {
                oneTmp = calc.negate(one);
            }
            else
            {
                oneTmp = calc.getCopy(one);
            }

            if (calc.mor(calc.zero, two))
            {
                twoTmp = calc.negate(two);
            }
            else
            {
                twoTmp = calc.getCopy(two);
            }

            try
            {
                while (!calc.eqv(oneTmp, calc.zero) && !calc.eqv(twoTmp, calc.zero))
                {
                    if (calc.mor(oneTmp, twoTmp))
                    {
                        oneTmp = calc.rem(oneTmp, twoTmp);
                    }
                    else
                    {
                        twoTmp = calc.rem(twoTmp, oneTmp);
                    }
                }
            }
            catch   // calculator throws exception - working with fp's.
            {
                oneTmp = calc.intPart(oneTmp);
                twoTmp = calc.intPart(twoTmp);

                while (!calc.eqv(oneTmp, calc.zero) && !calc.eqv(twoTmp, calc.zero))
                {
                    if (calc.mor(oneTmp, twoTmp))
                    {
                        oneTmp = WhiteMath <T, C> .Round(WhiteMath <T, C> .Modulus(oneTmp, twoTmp));
                    }
                    else
                    {
                        twoTmp = WhiteMath <T, C> .Round(WhiteMath <T, C> .Modulus(twoTmp, oneTmp));
                    }
                }
            }

            return(calc.sum(oneTmp, twoTmp));
        }