diff --git a/src/CLR/CorLib/corlib_native_System_Number.cpp b/src/CLR/CorLib/corlib_native_System_Number.cpp index 34a9939a03..b47b20ec3b 100644 --- a/src/CLR/CorLib/corlib_native_System_Number.cpp +++ b/src/CLR/CorLib/corlib_native_System_Number.cpp @@ -718,10 +718,11 @@ int Library_corlib_native_System_Number::Format_F( ret = DoPrintfOnDataType(buffer, formatStr, value); + bool isNegative = (buffer[0] == '-'); + // this extra processing is only required for integer types if (isIntegerDataType && ret > 0) { - bool isNegative = (buffer[0] == '-'); int offsetBecauseOfNegativeSign = (isNegative ? 1 : 0); int dotIndex = GetDotIndex(buffer, ret); @@ -756,6 +757,13 @@ int Library_corlib_native_System_Number::Format_F( ret = ReplaceNegativeSign(buffer, ret, negativeSign); ret = ReplaceDecimalSeparator(buffer, ret, decimalSeparator); } + else if (isNegative && ret == 2 && buffer[1] == '0') + { + // handle negative zero: if the value was negative but rounds to 0, remove the minus sign + // remove the negative sign + memmove(buffer, &buffer[1], ret); + ret--; + } return ret; } diff --git a/src/CLR/Helpers/nanoprintf/nanoprintf.c b/src/CLR/Helpers/nanoprintf/nanoprintf.c index a25294c366..7dcb438153 100644 --- a/src/CLR/Helpers/nanoprintf/nanoprintf.c +++ b/src/CLR/Helpers/nanoprintf/nanoprintf.c @@ -418,34 +418,39 @@ static char *format_float(double number, flt_width_t ndigits, flt_width_t width, { p -= (i - FLOAT_DIGITS); } - if (!(fflags & FF_NRND) && *p >= '5') + // Use the rounding digit at 'pend' (the extra generated digit) + if (!(fflags & FF_NRND) && *pend >= '5') { - for (;;) + char *start = buf +2; // first generated digit position + char *q = pend -1; // last significant digit + + // Set rounding digit to zero; it will be dropped later + *pend = '0'; + + // Propagate carry leftwards + while (q >= start && *q == '9') + { + *q = '0'; + --q; + } + + if (q < start) { - if (i == 0) + // Rollover past the most significant digit, e.g.,9.999 ->10.000 + *start = '1'; + ++decpt; + // In fixed 'f' mode, this increases displayed digits + if ((fflags & (FF_FCVT | FF_GCVT)) == FF_FCVT) { - // The rounding has rippled all the way through to - // the first digit. i.e. 9.999..9 -> 10.0 - // Just replace the first 0 with a 1 and shift the DP. - *p = '1'; - ++decpt; - // This increases the displayed digits for 'f' only. - if ((fflags & (FF_FCVT|FF_GCVT)) == FF_FCVT) - { - ++ndigits; - ++pend; - } - break; - } - // Previous digit was a rollover - *p-- = '0'; - // Increment next digit and break out unless there is a rollover. - if (*p != '9') - { - (*p)++; - break; + ++ndigits; + ++pend; // account for the added most significant digit } } + else + { + // Normal increment without rollover + (*q)++; + } } // Insert the decimal point @@ -910,6 +915,14 @@ static printf_t doprnt(void *context, void (*func)(char c, void *context), size_ } #endif #if FEATURE(USE_PRECISION) + // If precision explicitly set to 0 and value is 0, emit a single '0' + if (precision == 0 && uvalue == 0) + { + *--p = '0'; +#if FEATURE(USE_ZERO_PAD) + --fwidth; +#endif + } while (uvalue || precision > 0) #else if (uvalue == 0)