From 323c9b4df6df00f5242df39432e85ba1d95a349a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Fri, 31 Oct 2025 03:08:50 +0000 Subject: [PATCH 1/3] Reworked rounding logic in nanoprintf - Reworked the rounding logic to use the actual rounding digit (pend) and propagate carry correctly from the last significant digit leftwards. - Properly handles ripple (e.g., 9.8999 -> 10) and updates decpt/ndigits when needed in FF_FCVT mode. --- src/CLR/Helpers/nanoprintf/nanoprintf.c | 51 ++++++++++++++----------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/CLR/Helpers/nanoprintf/nanoprintf.c b/src/CLR/Helpers/nanoprintf/nanoprintf.c index a25294c366..bbad167e85 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') { - if (i == 0) - { - // 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') + *q = '0'; + --q; + } + + if (q < start) + { + // 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) { - (*p)++; - break; + ++ndigits; + ++pend; // account for the added most significant digit } } + else + { + // Normal increment without rollover + (*q)++; + } } // Insert the decimal point From 7d0cd4e8258abd892589d2f4a804281e52a08bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Fri, 31 Oct 2025 04:16:56 +0000 Subject: [PATCH 2/3] Handle negative 0 situation --- src/CLR/CorLib/corlib_native_System_Number.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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; } From 20f32a6bbbf4713ccf49e31fb13fc945a7b49d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Fri, 31 Oct 2025 04:30:27 +0000 Subject: [PATCH 3/3] Handle edge case with precision and value as 0 --- src/CLR/Helpers/nanoprintf/nanoprintf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/CLR/Helpers/nanoprintf/nanoprintf.c b/src/CLR/Helpers/nanoprintf/nanoprintf.c index bbad167e85..7dcb438153 100644 --- a/src/CLR/Helpers/nanoprintf/nanoprintf.c +++ b/src/CLR/Helpers/nanoprintf/nanoprintf.c @@ -915,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)