Esempio n. 1
0
            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);
            }