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); }
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; } }