Reported to me by Attila Feher. https://godbolt.org/z/djh5KxjW6
#include <format>
#include <iostream>
using namespace std;
int main() {
std::cout << "Expected: [1.e-37]\n";
std::cout << format(" Actual: [{:#6.0g}]\n", 1.234e-37);
}
libstdc++ and libc++ behave as expected, but MSVC prints:
Expected: [1.e-37]
Actual: [ 1.e-37]
🕵️ Analysis
I debugged into this, and although I'm not absolutely certain of the root cause yet, this line appears to be involved:
|
_Zeroes_to_append = _Extra_precision + _Precision - _Digits;
|
_Zeroes_to_append is computed as -1 because _Extra_precision and _Precision are both 0, and _Digits is 1.
We've correctly computed _Width to be 6, but the negative _Zeroes_to_append damages it, which appears to be the proximate cause of the bug:
|
_Width += _Zeroes_to_append;
|
Later, we use _Zeroes_to_append in a clamped manner (i.e. negative values are treated as zero):
|
for (; _Zeroes_to_append > 0; --_Zeroes_to_append) {
|
|
*_Out++ = '0';
|
|
}
|
However, we need to completely understand the problem and all possible codepaths before developing a fix (i.e. we can't just clamp it to zero and call it a day). Note that the chars_format::general codepath further adjusts _Zeroes_to_append:
|
_Zeroes_to_append = _Extra_precision + _Precision - _Digits;
|
|
|
|
// Leading zeroes are not significant if we used fixed point notation.
|
|
if (_Exponent_start == _Result.ptr && _STD abs(_Value) < 1.0 && _Value != 0.0) {
|
|
for (auto _It = _Buffer_start; _It < _Result.ptr; ++_It) {
|
|
if (*_It == '0') {
|
|
++_Zeroes_to_append;
|
|
} else if (*_It != '.') {
|
|
break;
|
|
}
|
|
}
|
|
}
|
Reported to me by Attila Feher. https://godbolt.org/z/djh5KxjW6
libstdc++ and libc++ behave as expected, but MSVC prints:
🕵️ Analysis
I debugged into this, and although I'm not absolutely certain of the root cause yet, this line appears to be involved:
STL/stl/inc/format
Line 2278 in 926d458
_Zeroes_to_appendis computed as-1because_Extra_precisionand_Precisionare both0, and_Digitsis1.We've correctly computed
_Widthto be6, but the negative_Zeroes_to_appenddamages it, which appears to be the proximate cause of the bug:STL/stl/inc/format
Line 2297 in 926d458
Later, we use
_Zeroes_to_appendin a clamped manner (i.e. negative values are treated as zero):STL/stl/inc/format
Lines 2328 to 2330 in 926d458
However, we need to completely understand the problem and all possible codepaths before developing a fix (i.e. we can't just clamp it to zero and call it a day). Note that the
chars_format::generalcodepath further adjusts_Zeroes_to_append:STL/stl/inc/format
Lines 2278 to 2289 in 926d458