示例#1
0
        private static unsafe void DoubleToNumber(double value, int precision, ref NumberBuffer number)
        {
            number.precision = precision;
            if (!Double.IsFinite(value))
            {
                number.scale     = Double.IsNaN(value) ? ScaleNAN : ScaleINF;
                number.sign      = Double.IsNegative(value);
                number.digits[0] = '\0';
            }
            else
            {
                byte *src = stackalloc byte[_CVTBUFSIZE];
                int   sign;
                fixed(NumberBuffer *pNumber = &number)
                {
                    RuntimeImports._ecvt_s(src, _CVTBUFSIZE, value, precision, &pNumber->scale, &sign);
                }

                number.sign = sign != 0;

                char *dst = number.digits;
                if ((char)*src != '0')
                {
                    while (*src != 0)
                    {
                        *dst++ = (char)*src++;
                    }
                }
                *dst = '\0';
            }
        }
示例#2
0
        //
        // Convert a Number to a double.
        //
        internal static bool NumberBufferToDouble(ref NumberBuffer number, out double value)
        {
            double d = NumberToDouble(ref number);

            if (!Double.IsFinite(d))
            {
                value = default;
                return(false);
            }

            if (d == 0.0)
            {
                // normalize -0.0 to 0.0
                d = 0.0;
            }

            value = d;
            return(true);
        }
示例#3
0
        private static unsafe void DoubleToNumber(double value, int precision, ref NumberBuffer number)
        {
            Debug.Assert(precision > 0 && precision < 40);

            number.precision = precision;
            if (!Double.IsFinite(value))
            {
                number.scale     = Double.IsNaN(value) ? ScaleNAN : ScaleINF;
                number.sign      = Double.IsNegative(value);
                number.digits[0] = '\0';
                return;
            }

            byte *tempBuffer = stackalloc byte[MAX_BUFFER_SIZE];
            char *dst        = number.digits;

            number.scale = 0;
            number.sign  = double.IsNegative(value);
            *dst = '\0';

            if (value == 0.0)
            {
                for (int j = 0; j < precision; j++)
                {
                    dst[j] = '0';
                }
                dst[precision] = '\0';
                return;
            }

            //
            // Get the number formatted as a string in the form x.xxxxxxexxxx
            //

            // "%.40e"
            byte *format = stackalloc byte[6];

            format[0] = (byte)'%';
            format[1] = (byte)'.';
            format[2] = (byte)'4';
            format[3] = (byte)'0';
            format[4] = (byte)'e';
            format[5] = 0;

            int tempBufferLength = Interop.Sys.DoubleToString(value, format, tempBuffer, MAX_BUFFER_SIZE);

            Debug.Assert(tempBufferLength > 0 && MAX_BUFFER_SIZE > tempBufferLength);

            //
            // Calculate the exponent value
            //

            int exponentIndex = tempBufferLength - 1;

            while (tempBuffer[exponentIndex] != (byte)'e' && exponentIndex > 0)
            {
                exponentIndex--;
            }

            Debug.Assert(exponentIndex > 0 && (exponentIndex < tempBufferLength - 1));

            int i            = exponentIndex + 1;
            int exponentSign = 1;

            if (tempBuffer[i] == '-')
            {
                exponentSign = -1;
                i++;
            }
            else if (tempBuffer[i] == '+')
            {
                i++;
            }

            int exponentValue = 0;

            while (i < tempBufferLength)
            {
                Debug.Assert(tempBuffer[i] >= (byte)'0' && tempBuffer[i] <= (byte)'9');
                exponentValue = exponentValue * 10 + (tempBuffer[i] - (byte)'0');
                i++;
            }
            exponentValue *= exponentSign;

            //
            // Determine decimal location.
            //

            if (exponentValue == 0)
            {
                number.scale = 1;
            }
            else
            {
                number.scale = exponentValue + 1;
            }

            //
            // Copy the string from the temp buffer upto precision characters, removing the sign, and decimal as required.
            //

            i = 0;
            int mantissaIndex = 0;

            while (i < precision && mantissaIndex < exponentIndex)
            {
                if (tempBuffer[mantissaIndex] >= (byte)'0' && tempBuffer[mantissaIndex] <= (byte)'9')
                {
                    dst[i] = (char)tempBuffer[mantissaIndex];
                    i++;
                }
                mantissaIndex++;
            }

            while (i < precision)
            {
                dst[i] = '0'; // append zeros as needed
                i++;
            }

            dst[i] = '\0';

            //
            // Round if needed
            //

            if (mantissaIndex >= exponentIndex || tempBuffer[mantissaIndex] < (byte)'5')
            {
                return; // rounding is not needed
            }

            i = precision - 1;
            while (dst[i] == '9' && i > 0)
            {
                dst[i] = '0';
                i--;
            }

            if (i == 0 && dst[i] == '9')
            {
                dst[i] = '1';
                number.scale++;
            }
            else
            {
                dst[i]++;
            }
        }