Jurassic.BigInteger.Add C# (CSharp) Method

Add() public static method

Adds two BigInteger values and returns the result.
public static Add ( BigInteger left, BigInteger right ) : BigInteger
left BigInteger The first value to add.
right BigInteger The second value to add.
return BigInteger
        public static BigInteger Add(BigInteger left, BigInteger right)
        {
            // 0 + right = right
            if (left.Sign == 0)
                return right;

            // left + 0 = left
            if (right.Sign == 0)
                return left;

            // If the signs of the two numbers are different, do a subtract instead.
            if (left.Sign != right.Sign)
                return Subtract(left, Negate(right));

            // From here the sign of both numbers is the same.
            int outputWordCount = Math.Max(left.wordCount, right.wordCount);
            uint[] outputBits = new uint[outputWordCount + 1];

            uint borrow = 0;
            int i = 0;
            for (; i < Math.Min(left.wordCount, right.wordCount); i++)
            {
                ulong temp = (ulong)left.bits[i] + right.bits[i] + borrow;
                borrow = (uint)(temp >> 32);
                outputBits[i] = (uint)temp;
            }
            if (left.wordCount > right.wordCount)
            {
                for (; i < left.wordCount; i++)
                {
                    ulong temp = (ulong)left.bits[i] + borrow;
                    borrow = (uint)(temp >> 32);
                    outputBits[i] = (uint)temp;
                }
            }
            else if (left.wordCount < right.wordCount)
            {
                for (; i < right.wordCount; i++)
                {
                    ulong temp = (ulong)right.bits[i] + borrow;
                    borrow = (uint)(temp >> 32);
                    outputBits[i] = (uint)temp;
                }
            }
            if (borrow != 0)
            {
                outputBits[outputWordCount] = borrow;
                outputWordCount++;
            }
            return new BigInteger(outputBits, outputWordCount, left.Sign);
        }

Usage Example

示例#1
0
        /// <summary>
        /// Parses a number and returns the corresponding double-precision value.
        /// </summary>
        /// <param name="reader"> The reader to read characters from. </param>
        /// <param name="firstChar"> The first character of the number.  Must be 0-9 or a period. </param>
        /// <param name="status"> Upon returning, contains the type of error if one occurred. </param>
        /// <param name="decimalOnly"> </param>
        /// <param name="allowES3Octal"> </param>
        /// <returns> The numeric value, or <c>NaN</c> if the number is invalid. </returns>
        internal static double ParseCore(TextReader reader, char firstChar, out ParseCoreStatus status, bool decimalOnly = false, bool allowES3Octal = true)
        {
            double result;

            // A count of the number of integral and fractional digits of the input number.
            int totalDigits = 0;

            // Assume success.
            status = ParseCoreStatus.Success;

            // If the number starts with '0' then the number is a hex literal, octal literal or binary literal.
            if (firstChar == '0' && decimalOnly == false)
            {
                // Read the next char - should be 'x' or 'X' if this is a hex number (could be just '0').
                int c = reader.Peek();
                if (c == 'x' || c == 'X')
                {
                    // Hex number.
                    reader.Read();

                    result = ParseHex(reader);
                    if (double.IsNaN(result) == true)
                    {
                        status = ParseCoreStatus.InvalidHexLiteral;
                        return(double.NaN);
                    }
                    status = ParseCoreStatus.HexLiteral;
                    return(result);
                }
                else if (c == 'o' || c == 'O')
                {
                    // ES6 octal number.
                    reader.Read();

                    result = ParseOctal(reader);
                    if (double.IsNaN(result) == true)
                    {
                        status = ParseCoreStatus.InvalidOctalLiteral;
                        return(double.NaN);
                    }
                    status = ParseCoreStatus.ES6OctalLiteral;
                    return(result);
                }
                else if (c == 'b' || c == 'B')
                {
                    // ES6 binary number.
                    reader.Read();

                    result = ParseBinary(reader);
                    if (double.IsNaN(result) == true)
                    {
                        status = ParseCoreStatus.InvalidBinaryLiteral;
                        return(double.NaN);
                    }
                    status = ParseCoreStatus.BinaryLiteral;
                    return(result);
                }
                else if (c >= '0' && c <= '9' && allowES3Octal == true)
                {
                    // ES3 Octal number.
                    result = ParseOctal(reader);
                    if (double.IsNaN(result) == true)
                    {
                        status = ParseCoreStatus.InvalidOctalLiteral;
                        return(double.NaN);
                    }
                    status = ParseCoreStatus.ES3OctalLiteral;
                    return(result);
                }
            }

            // desired1-3 hold the integral and fractional digits of the input number.
            // desired1 holds the first set of nine digits, desired2 holds the second set of nine
            // digits, desired3 holds the rest.
            int desired1 = 0;
            int desired2 = 0;
            var desired3 = BigInteger.Zero;

            // Indicates the base-10 scale factor of the output e.g. the result is
            // desired x 10^exponentBase10.
            int exponentBase10 = 0;

            // Read the integer component.
            if (firstChar >= '0' && firstChar <= '9')
            {
                desired1    = firstChar - '0';
                totalDigits = 1;
                while (true)
                {
                    int c = reader.Peek();
                    if (c < '0' || c > '9')
                    {
                        break;
                    }
                    reader.Read();

                    if (totalDigits < 9)
                    {
                        desired1 = desired1 * 10 + (c - '0');
                    }
                    else if (totalDigits < 18)
                    {
                        desired2 = desired2 * 10 + (c - '0');
                    }
                    else
                    {
                        desired3 = BigInteger.MultiplyAdd(desired3, 10, c - '0');
                    }
                    totalDigits++;
                }
            }

            if (firstChar == '.' || reader.Peek() == '.')
            {
                // Skip past the period.
                if (firstChar != '.')
                {
                    reader.Read();
                }

                // Read the fractional component.
                int fractionalDigits = 0;
                while (true)
                {
                    int c = reader.Peek();
                    if (c < '0' || c > '9')
                    {
                        break;
                    }
                    reader.Read();

                    if (totalDigits < 9)
                    {
                        desired1 = desired1 * 10 + (c - '0');
                    }
                    else if (totalDigits < 18)
                    {
                        desired2 = desired2 * 10 + (c - '0');
                    }
                    else
                    {
                        desired3 = BigInteger.MultiplyAdd(desired3, 10, c - '0');
                    }
                    totalDigits++;
                    fractionalDigits++;
                    exponentBase10--;
                }

                // Check if the number consists solely of a period.
                if (totalDigits == 0)
                {
                    status = ParseCoreStatus.NoDigits;
                    return(double.NaN);
                }

                // Check if the number has a period but no digits afterwards.
                if (fractionalDigits == 0)
                {
                    status = ParseCoreStatus.NoFraction;
                }
            }

            if (reader.Peek() == 'e' || reader.Peek() == 'E')
            {
                // Skip past the 'e'.
                reader.Read();

                // Read the sign of the exponent.
                bool exponentNegative = false;
                int  c = reader.Peek();
                if (c == '+')
                {
                    reader.Read();
                }
                else if (c == '-')
                {
                    reader.Read();
                    exponentNegative = true;
                }

                // Read the first character of the exponent.
                int firstExponentChar = reader.Read();

                // Check there is a number after the 'e'.
                int exponent = 0;
                if (firstExponentChar < '0' || firstExponentChar > '9')
                {
                    status = ParseCoreStatus.NoExponent;
                }
                else
                {
                    // Read the rest of the exponent.
                    exponent = firstExponentChar - '0';
                    int exponentDigits = 1;
                    while (true)
                    {
                        c = reader.Peek();
                        if (c < '0' || c > '9')
                        {
                            break;
                        }
                        reader.Read();
                        exponent = Math.Min(exponent * 10 + (c - '0'), 9999);
                        exponentDigits++;
                    }

                    // JSON does not allow a leading zero in front of the exponent.
                    if (firstExponentChar == '0' && exponentDigits > 1 && status == ParseCoreStatus.Success)
                    {
                        status = ParseCoreStatus.ExponentHasLeadingZero;
                    }
                }

                // Keep track of the overall base-10 exponent.
                exponentBase10 += exponentNegative ? -exponent : exponent;
            }

            // Calculate the integral and fractional portion of the number, scaled to an integer.
            if (totalDigits < 16)
            {
                // Combine desired1 and desired2 to produce an integer representing the final
                // result.
                result = (double)((long)desired1 * integerPowersOfTen[Math.Max(totalDigits - 9, 0)] + desired2);
            }
            else
            {
                // Combine desired1, desired2 and desired3 to produce an integer representing the
                // final result.
                var temp = desired3;
                desired3 = new BigInteger((long)desired1 * integerPowersOfTen[Math.Min(totalDigits - 9, 9)] + desired2);
                if (totalDigits > 18)
                {
                    desired3 = BigInteger.Multiply(desired3, BigInteger.Pow(10, totalDigits - 18));
                    desired3 = BigInteger.Add(desired3, temp);
                }
                result = desired3.ToDouble();
            }

            // Apply the base-10 exponent.
            if (exponentBase10 > 0)
            {
                result *= Math.Pow(10, exponentBase10);
            }
            else if (exponentBase10 < 0 && exponentBase10 >= -308)
            {
                result /= Math.Pow(10, -exponentBase10);
            }
            else if (exponentBase10 < -308)
            {
                // Note: 10^308 is the largest representable power of ten.
                result /= Math.Pow(10, 308);
                result /= Math.Pow(10, -exponentBase10 - 308);
            }

            // Numbers with 16 or more digits require the use of arbitrary precision arithmetic to
            // determine the correct answer.
            if (totalDigits >= 16)
            {
                return(RefineEstimate(result, exponentBase10, desired3));
            }

            return(result);
        }