public static bool Run(double value, int precision, ref NumberBuffer number) { // ======================================================================================================================================== // This implementation is based on the paper: http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf // You must read this paper to fully understand the code. // // Deviation: Instead of generating shortest digits, we generate the digits according to the input count. // Therefore, we do not need m+ and m- which are used to determine the exact range of values. // ======================================================================================================================================== // // Overview: // // The idea of Grisu3 is to leverage additional bits and cached power of ten to produce the digits. // We need to create a handmade floating point data structure DiyFp to extend the bits of double. // We also need to cache the powers of ten for digits generation. By choosing the correct index of powers // we need to start with, we can eliminate the expensive big num divide operation. // // Grisu3 is imprecision for some numbers. Fortunately, the algorithm itself can determine that and give us // a success/fail flag. We may fall back to other algorithms (For instance, Dragon4) if it fails. // // w: the normalized DiyFp from the input value. // mk: The index of the cached powers. // cmk: The cached power. // D: Product: w * cmk. // kappa: A factor used for generating digits. See step 5 of the Grisu3 procedure in the paper. // Handle sign bit. if (double.IsNegative(value)) { value = -value; number.IsNegative = true; } else { number.IsNegative = false; } // Step 1: Determine the normalized DiyFp w. DiyFp.GenerateNormalizedDiyFp(value, out DiyFp w); // Step 2: Find the cached power of ten. // Compute the proper index mk. int mk = KComp(w.e + DiyFp.SignificandLength); // Retrieve the cached power of ten. CachedPower(mk, out DiyFp cmk, out int decimalExponent); // Step 3: Scale the w with the cached power of ten. DiyFp.Multiply(ref w, ref cmk, out DiyFp D); // Step 4: Generate digits. bool isSuccess = DigitGen(ref D, precision, number.GetDigitsPointer(), out int length, out int kappa); if (isSuccess) { number.Digits[precision] = (byte)('\0'); number.Scale = (length - decimalExponent + kappa); } return(isSuccess); }