public static void DoubleToAscii(
            DtoaBuilder buffer,
            double v,
            DtoaMode mode,
            int requested_digits,
            out bool negative,
            out int point)
        {
            Debug.Assert(!double.IsNaN(v));
            Debug.Assert(!double.IsInfinity(v));
            Debug.Assert(mode == DtoaMode.Shortest || requested_digits >= 0);

            point    = 0;
            negative = false;
            buffer.Reset();

            if (v < 0)
            {
                negative = true;
                v        = -v;
            }

            if (v == 0)
            {
                buffer[0] = '0';
                point     = 1;
                return;
            }

            if (mode == DtoaMode.Precision && requested_digits == 0)
            {
                return;
            }

            bool fast_worked = false;

            switch (mode)
            {
            case DtoaMode.Shortest:
                fast_worked = FastDtoa.NumberToString(v, DtoaMode.Shortest, 0, out point, buffer);
                break;

            case DtoaMode.Fixed:
                //fast_worked = FastFixedDtoa(v, requested_digits, buffer, length, point);
                ExceptionHelper.ThrowNotImplementedException();
                break;

            case DtoaMode.Precision:
                fast_worked = FastDtoa.NumberToString(v, DtoaMode.Precision, requested_digits, out point, buffer);
                break;

            default:
                ExceptionHelper.ThrowArgumentOutOfRangeException <string>();
                return;
            }

            if (fast_worked)
            {
                return;
            }

            // If the fast dtoa didn't succeed use the slower bignum version.
            buffer.Reset();
            BignumDtoa.NumberToString(v, mode, requested_digits, buffer, out point);
        }
Beispiel #2
0
        public static void NumberToString(
            double v,
            DtoaMode mode,
            int requested_digits,
            DtoaBuilder builder,
            out int decimal_point)
        {
            var bits                = (ulong)BitConverter.DoubleToInt64Bits(v);
            var significand         = DoubleHelper.Significand(bits);
            var is_even             = (significand & 1) == 0;
            var exponent            = DoubleHelper.Exponent(bits);
            var normalized_exponent = DoubleHelper.NormalizedExponent(significand, exponent);
            // estimated_power might be too low by 1.
            var estimated_power = EstimatePower(normalized_exponent);

            // Shortcut for Fixed.
            // The requested digits correspond to the digits after the point. If the
            // number is much too small, then there is no need in trying to get any
            // digits.
            if (mode == DtoaMode.Fixed && -estimated_power - 1 > requested_digits)
            {
                // Set decimal-point to -requested_digits. This is what Gay does.
                // Note that it should not have any effect anyways since the string is
                // empty.
                decimal_point = -requested_digits;
                return;
            }

            Bignum numerator   = new Bignum();
            Bignum denominator = new Bignum();
            Bignum delta_minus = new Bignum();
            Bignum delta_plus  = new Bignum();
            // Make sure the bignum can grow large enough. The smallest double equals
            // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
            // The maximum double is 1.7976931348623157e308 which needs fewer than
            // 308*4 binary digits.
            var need_boundary_deltas = mode == DtoaMode.Shortest;

            InitialScaledStartValues(
                v,
                estimated_power,
                need_boundary_deltas,
                numerator,
                denominator,
                delta_minus,
                delta_plus);
            // We now have v = (numerator / denominator) * 10^estimated_power.
            FixupMultiply10(
                estimated_power,
                is_even,
                out decimal_point,
                numerator,
                denominator,
                delta_minus,
                delta_plus);
            // We now have v = (numerator / denominator) * 10^(decimal_point-1), and
            //  1 <= (numerator + delta_plus) / denominator < 10
            switch (mode)
            {
            case DtoaMode.Shortest:
                GenerateShortestDigits(
                    numerator,
                    denominator,
                    delta_minus,
                    delta_plus,
                    is_even,
                    builder);
                break;

            case DtoaMode.Fixed:
                BignumToFixed(
                    requested_digits,
                    ref decimal_point,
                    numerator,
                    denominator,
                    builder);
                break;

            case DtoaMode.Precision:
                GenerateCountedDigits(
                    requested_digits,
                    ref decimal_point,
                    numerator,
                    denominator,
                    builder);
                break;

            default:
                ExceptionHelper.ThrowArgumentOutOfRangeException();
                break;
            }
        }