Jurassic.BigInteger.FromDouble C# (CSharp) Method

FromDouble() public static method

Returns a new instance BigInteger structure from a 64-bit double precision floating point value.
public static FromDouble ( double value ) : BigInteger
value double A 64-bit double precision floating point value.
return BigInteger
        public static BigInteger FromDouble(double value)
        {
            long bits = BitConverter.DoubleToInt64Bits(value);

            // Extract the base-2 exponent.
            var base2Exponent = (int)((bits & 0x7FF0000000000000) >> 52) - 1023;

            // Extract the mantissa.
            long mantissa = bits & 0xFFFFFFFFFFFFF;
            if (base2Exponent > -1023)
            {
                mantissa |= 0x10000000000000;
                base2Exponent -= 52;
            }
            else
            {
                // Denormals.
                base2Exponent -= 51;
            }

            // Extract the sign bit.
            if (bits < 0)
                mantissa = -mantissa;

            return BigInteger.LeftShift(new BigInteger(mantissa), base2Exponent);
        }

Usage Example

        /// <summary>
        /// Converts a string to an integer (used by parseInt).
        /// </summary>
        /// <param name="radix"> The numeric base to use for parsing.  Pass zero to use base 10
        /// except when the input string starts with '0' in which case base 16 or base 8 are used
        /// instead. </param>
        /// <param name="allowOctal"> <c>true</c> if numbers with a leading zero should be parsed
        /// as octal numbers. </param>
        /// <returns> The result of parsing the string as a integer. </returns>
        internal static double ParseInt(string input, int radix, bool allowOctal)
        {
            var reader     = new System.IO.StringReader(input);
            int digitCount = 0;

            // Skip whitespace and line terminators.
            while (IsWhiteSpaceOrLineTerminator(reader.Peek()))
            {
                reader.Read();
            }

            // Determine the sign.
            double sign = 1;

            if (reader.Peek() == '+')
            {
                reader.Read();
            }
            else if (reader.Peek() == '-')
            {
                sign = -1;
                reader.Read();
            }

            // Hex prefix should be stripped if the radix is 0, undefined or 16.
            bool stripPrefix = radix == 0 || radix == 16;

            // Default radix is 10.
            if (radix == 0)
            {
                radix = 10;
            }

            // Skip past the prefix, if there is one.
            if (stripPrefix == true)
            {
                if (reader.Peek() == '0')
                {
                    reader.Read();
                    digitCount = 1;     // Note: required for parsing "0z11" correctly (when radix = 0).

                    int c = reader.Peek();
                    if (c == 'x' || c == 'X')
                    {
                        // Hex number.
                        reader.Read();
                        radix = 16;
                    }

                    if (c >= '0' && c <= '9' && allowOctal == true)
                    {
                        // Octal number.
                        radix = 8;
                    }
                }
            }

            // Calculate the maximum number of digits before arbitrary precision arithmetic is
            // required.
            int maxDigits = (int)Math.Floor(53 / Math.Log(radix, 2));

            // Read numeric digits 0-9, a-z or A-Z.
            double result    = 0;
            var    bigResult = BigInteger.Zero;

            while (true)
            {
                int numericValue = -1;
                int c            = reader.Read();
                if (c >= '0' && c <= '9')
                {
                    numericValue = c - '0';
                }
                if (c >= 'a' && c <= 'z')
                {
                    numericValue = c - 'a' + 10;
                }
                if (c >= 'A' && c <= 'Z')
                {
                    numericValue = c - 'A' + 10;
                }
                if (numericValue == -1 || numericValue >= radix)
                {
                    break;
                }
                if (digitCount == maxDigits)
                {
                    bigResult = BigInteger.FromDouble(result);
                }
                result = result * radix + numericValue;
                if (digitCount >= maxDigits)
                {
                    bigResult = BigInteger.MultiplyAdd(bigResult, radix, numericValue);
                }
                digitCount++;
            }

            // If the input is empty, then return NaN.
            if (digitCount == 0)
            {
                return(double.NaN);
            }

            // Numbers with lots of digits require the use of arbitrary precision arithmetic to
            // determine the correct answer.
            if (digitCount > maxDigits)
            {
                return(RefineEstimate(result, 0, bigResult) * sign);
            }

            return(result * sign);
        }