private static bool NumberBufferToDouble(ref NumberBuffer number, ref double value) { double d = NumberToDouble(ref number); uint e = DoubleHelper.Exponent(d); ulong m = DoubleHelper.Mantissa(d); if (e == 0x7FF) { return(false); } if (e == 0 && m == 0) { d = 0; } value = d; return(true); }
private static unsafe void DoubleToNumber(double value, int precision, ref NumberBuffer number) { Debug.Assert(precision > 0 && precision < 40); number.precision = precision; if (DoubleHelper.Exponent(value) == 0x7ff) { number.scale = DoubleHelper.Mantissa(value) != 0 ? SCALE_NAN : SCALE_INF; number.sign = DoubleHelper.Sign(value); number.digits[0] = '\0'; return; } byte *tempBuffer = stackalloc byte[MAX_BUFFER_SIZE]; char *dst = number.digits; number.scale = 0; number.sign = false; *dst = '\0'; if (value < 0.0) { number.sign = true; } 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]++; } }