Ejemplo n.º 1
0
        public static BigDouble Normalize(double mantissa, long exponent)
        {
            if (mantissa >= 1 && mantissa < 10 || !IsFinite(mantissa))
            {
                return(new BigDouble(mantissa, exponent));
            }
            if (IsZero(mantissa))
            {
                return(Zero);
            }

            var tempExponent = (long)Math.Floor(Math.Log10(Math.Abs(mantissa)));

            //SAFETY: handle 5e-324, -5e-324 separately
            if (tempExponent == DoubleExpMin)
            {
                mantissa = mantissa * 10 / 1e-323;
            }
            else
            {
                mantissa = mantissa / PowersOf10.Lookup(tempExponent);
            }

            return(new BigDouble(mantissa, exponent + tempExponent));
        }
Ejemplo n.º 2
0
        public static BigDouble Add(BigDouble left, BigDouble right)
        {
            //figure out which is bigger, shrink the mantissa of the smaller by the difference in exponents, add mantissas, normalize and return

            //TODO: Optimizations and simplification may be possible, see https://github.com/Patashu/break_infinity.js/issues/8

            if (IsZero(left.Mantissa))
            {
                return(right);
            }

            if (IsZero(right.Mantissa))
            {
                return(left);
            }

            if (IsNaN(left) || IsNaN(right) || IsInfinity(left) || IsInfinity(right))
            {
                // Let Double handle these cases.
                return(left.Mantissa + right.Mantissa);
            }

            BigDouble bigger, smaller;

            if (left.Exponent >= right.Exponent)
            {
                bigger  = left;
                smaller = right;
            }
            else
            {
                bigger  = right;
                smaller = left;
            }

            if (bigger.Exponent - smaller.Exponent > MaxSignificantDigits)
            {
                return(bigger);
            }

            //have to do this because adding numbers that were once integers but scaled down is imprecise.
            //Example: 299 + 18
            return(Normalize(
                       Math.Round(1e14 * bigger.Mantissa + 1e14 * smaller.Mantissa *
                                  PowersOf10.Lookup(smaller.Exponent - bigger.Exponent)),
                       bigger.Exponent - 14));
        }
Ejemplo n.º 3
0
        public double ToDouble()
        {
            if (IsNaN(this))
            {
                return(double.NaN);
            }

            if (Exponent > DoubleExpMax)
            {
                return(Mantissa > 0 ? double.PositiveInfinity : double.NegativeInfinity);
            }

            if (Exponent < DoubleExpMin)
            {
                return(0.0);
            }

            //SAFETY: again, handle 5e-324, -5e-324 separately
            if (Exponent == DoubleExpMin)
            {
                return(Mantissa > 0 ? 5e-324 : -5e-324);
            }

            var result = Mantissa * PowersOf10.Lookup(Exponent);

            if (!IsFinite(result) || Exponent < 0)
            {
                return(result);
            }

            var resultrounded = Math.Round(result);

            if (Math.Abs(resultrounded - result) < 1e-10)
            {
                return(resultrounded);
            }
            return(result);
        }