https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120967
Bug ID: 120967 Summary: std::format produces incorrect results when printing large floating point numbers when using the alternate flag and precision set to 0 Product: gcc Version: 14.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: dominick.allen1989 at gmail dot com Target Milestone: --- Created attachment 61806 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61806&action=edit Bug reproducing input file When printing using format specifications, be it std::print or std::format, the use of the alternate flag with a precision of 0 produces incorrect results where the decimal point is off by one, and a leading null terminating byte is present. The transition point for a suitably large number happens to be `std::numeric_limits<double>::max() / exp2(512 + 64 + 16 + 8 + 2)`, where after that point the correct behavior is present. This is only the case for libstdc++; clang only reproduces this behavior if it is not configured to use libc++, in which case it produces correct results. ``` #include <cmath> #include <limits> #include <format> #include <cstdio> #include <print> #include <iostream> void demoBug(double value) { std::print("Printing {:e} with std::print and std::format\n", value); std::print("With std::print\n{0:#.0f}\n{0:f}\n", value); std::print("With std::format\n"); auto output1 = std::format("{:#.0f}\n", value); auto output2 = std::format("{:f}\n", value); std::cout << output1; std::cout << std::format("{:f}\n", value); std::print("The first byte of output1 is {:#X}\n", output1[0]); std::print("The first byte of output2 is {:#X}\n", output2[0]); } int main() { demoBug(std::numeric_limits<double>::max()); std::print("Printing {:e} printf\n", std::numeric_limits<double>::max()); printf("%#010.0f\n%f\n", std::numeric_limits<double>::max(), std::numeric_limits<double>::max()); demoBug(std::numeric_limits<double>::max() / exp2(512 + 64 + 16 + 8 + 2)); demoBug(std::numeric_limits<double>::max() / exp2(512 + 64 + 16 + 8 + 2 + 1)); return 0; } ``` Output: ``` libfud@localhost ~/Documents/bug_reports/format $ g++ -std=c++23 main.cpp -o format_float_fixed && ./format_float_fixed Printing 1.797693e+308 with std::print and std::format With std::print 17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873817718091929988125040402618412485836.8 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 With std::format 17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873817718091929988125040402618412485836.8 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 The first byte of output1 is 0X0 The first byte of output2 is 0X31 Printing 1.797693e+308 printf 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368. 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 Printing 1.083074e+127 with std::print and std::format With std::print 1083074099265943184277437802660630803713451676954622548041022082071609068148274766550887916516477217352904724481640675010622259.2 10830740992659431842774378026606308037134516769546225480410220820716090681482747665508879165164772173529047244816406750106222592.000000 With std::format 1083074099265943184277437802660630803713451676954622548041022082071609068148274766550887916516477217352904724481640675010622259.2 10830740992659431842774378026606308037134516769546225480410220820716090681482747665508879165164772173529047244816406750106222592.000000 The first byte of output1 is 0X0 The first byte of output2 is 0X31 Printing 5.415370e+126 with std::print and std::format With std::print 5415370496329715921387189013303154018567258384773112740205110410358045340741373832754439582582386086764523622408203375053111296. 5415370496329715921387189013303154018567258384773112740205110410358045340741373832754439582582386086764523622408203375053111296.000000 With std::format 5415370496329715921387189013303154018567258384773112740205110410358045340741373832754439582582386086764523622408203375053111296. 5415370496329715921387189013303154018567258384773112740205110410358045340741373832754439582582386086764523622408203375053111296.000000 The first byte of output1 is 0X35 The first byte of output2 is 0X35 ``` https://godbolt.org/z/qdvc34KrW Output of `g++ -v`: Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/14/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-pc-linux-gnu Configured with: /var/tmp/portage/sys-devel/gcc-14.3.0/work/gcc-14.3.0/configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/14 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/14/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/14 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/14/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/14/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14 --disable-silent-rules --disable-dependency-tracking --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/14/python --enable-languages=c,c++,fortran --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --disable-libunwind-exceptions --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 14.3.0 p8' --with-gcc-major-version-only --enable-libstdcxx-time --enable-lto --disable-libstdcxx-pch --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-multilib --with-multilib-list=m32,m64 --disable-fixed-point --enable-targets=all --enable-offload-defaulted --enable-offload-targets=nvptx-none --enable-libgomp --disable-libssp --disable-libada --enable-cet --disable-systemtap --disable-valgrind-annotations --disable-vtable-verify --disable-libvtv --with-zstd --without-isl --enable-default-pie --enable-host-pie --enable-host-bind-now --enable-default-ssp --disable-fixincludes --with-gxx-libcxx-include-dir=/usr/include/c++/v1 --with-build-config=bootstrap-cet Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 14.3.0 (Gentoo 14.3.0 p8)