From: sisyphus <sis...@gm...> - 2024-05-07 11:05:35
|
Hi, Demo program: /*********** DBL_MAX.c ***********/ #include <stdio.h> #define MY_DBL_MAX 0x1.fffffffffffffp+1023 int main(void) { if(MY_DBL_MAX == 1.7976931348623157e+308) printf("OK1\n"); else printf("%a\n%a\n", MY_DBL_MAX, 1.7976931348623157e+308); return 0; } /*********************************/ If I build the executable with: gcc -o DBL_MAX.exe DBL_MAX.c then the executable outputs "OK1" as expected. But if I build with: gcc -o DBL_MAX.exe DBL_MAX.c -std=c99 then the output changes to: 0x1.fffffffffffffp+1023 0x1.fffffffffffffp+1023 Why does this happen ? It happens with: gcc version 8.3.0 (i686-posix-dwarf, Built by strawberryperl.com project) gcc version 10.3.0 (MinGW-W64 i686-posix-dwarf, built by Brecht Sanders) gcc version 11.3.0 (MinGW-W64 i686-posix-dwarf, built by Brecht Sanders) gcc version 12.2.0 (MinGW-W64 i686-msvcrt-posix-dwarf, built by Brecht Sanders) gcc version 13.1.0 (MinGW-W64 i686-msvcrt-mcf-dwarf, built by Brecht Sanders) gcc version 13.2.0 (MinGW-W64 i686-ucrt-mcf-dwarf, built by Brecht Sanders, r3) Those are the only 32-bit compilers I've tested. 64-bit compilers seem to be unaffected by this issue. Although I often test 32-bit gcc on Windows, I don't actually rely on those compilers - so I don't personally need a fix. I just wanted to mention this issue in case it's in the "public interest". Cheers, Rob |
From: LIU H. <lh_...@12...> - 2024-05-07 15:09:49
Attachments:
OpenPGP_signature.asc
|
在 2024-05-07 19:05, sisyphus 写道: > Although I often test 32-bit gcc on Windows, I don't actually rely on those > compilers - so I don't personally need a fix. > I just wanted to mention this issue in case it's in the "public interest". It looks like this is caused by `-fexcess-precision=standard`, as in GCC manual: -fexcess-precision=style This option allows further control over excess precision on machines where floating-point operations occur in a format with more precision or range than the IEEE standard and interchange floating-point types. By default, -fexcessprecision=fast is in effect; this means that operations may be carried out in a wider precision than the types specified in the source if that would result in faster code, and it is unpredictable when rounding to the types specified in the source code takes place. When compiling C or C++, if -fexcessprecision=standard is specified then excess precision follows the rules specified in ISO C99 or C++; in particular, both casts and assignments cause values to be rounded to their semantic types (whereas -ffloat-store only affects assignments). This option is enabled by default for C or C++ if a strict conformance option such as -std=c99 or -std=c++17 is used. -ffast-math enables -fexcess-precision=fast by default regardless of whether a strict conformance option is used. -fexcess-precision=standard is not implemented for languages other than C or C++. On the x86, it has no effect if -mfpmath=sse or -mfpmath=sse+387 is specified; in the former case, IEEE semantics apply without excess precision, and in the latter, rounding is unpredictable. By default the x87 FPU is used for floating-point arithmetic, so `1.7976931348623157e+308` is more precise than `double` and does not equal `0x1.fffffffffffffp+1023` due to the extra significant bits. x86-64 is not subject to this, as SSE registers are exact `double` and there is no excess precision. -- Best regards, LIU Hao |
From: sisyphus <sis...@gm...> - 2024-05-08 08:34:10
|
Thanks for the detailed explanation. I now realize that there are many different values that are similarly affected. Cheers, Rob On Wed, May 8, 2024 at 1:09 AM LIU Hao <lh_...@12...> wrote: > 在 2024-05-07 19:05, sisyphus 写道: > > Although I often test 32-bit gcc on Windows, I don't actually rely on > those > > compilers - so I don't personally need a fix. > > I just wanted to mention this issue in case it's in the "public > interest". > > It looks like this is caused by `-fexcess-precision=standard`, as in GCC > manual: > > -fexcess-precision=style > > This option allows further control over excess precision on machines > where floating-point operations occur in a format with more precision > or range than the IEEE standard and interchange floating-point types. > By default, -fexcessprecision=fast is in effect; this means that > operations may be carried out in a wider precision than the types > specified in the source if that would result in faster code, and it is > unpredictable when rounding to the types specified in the source code > takes place. When compiling C or C++, if -fexcessprecision=standard is > specified then excess precision follows the rules specified in ISO C99 > or C++; in particular, both casts and assignments cause values to be > rounded to their semantic types (whereas -ffloat-store only affects > assignments). This option is enabled by default for C or C++ if a > strict conformance option such as -std=c99 or -std=c++17 is used. > -ffast-math enables -fexcess-precision=fast by default regardless of > whether a strict conformance option is used. > > -fexcess-precision=standard is not implemented for languages other > than C or C++. On the x86, it has no effect if -mfpmath=sse or > -mfpmath=sse+387 is specified; in the former case, IEEE semantics > apply without excess precision, and in the latter, rounding is > unpredictable. > > > By default the x87 FPU is used for floating-point arithmetic, so > `1.7976931348623157e+308` is more > precise than `double` and does not equal `0x1.fffffffffffffp+1023` due to > the extra significant bits. > > x86-64 is not subject to this, as SSE registers are exact `double` and > there is no excess precision. > > > -- > Best regards, > LIU Hao > > |