gcc 11.1.0: printf("%.43f\n", 0x1.52f8a8e32e982p-140): printed value is incorrectly rounded

Brian Inglis Brian.Inglis@SystematicSw.ab.ca
Sun Jun 13 19:19:38 GMT 2021


On 2021-06-12 14:45, Pavel M via Cygwin wrote:
> Sample code (t903.c):
> #include <stdio.h>
> int main(void)
> {
>      printf("%.43f\n", 0x1.52f8a8e32e982p-140);
>      return 0;
> }
> 
> Invocations:
> # gcc on Windows 10 (Cygwin)
> $ gcc t903.c -Wall -Wextra -std=c11 -pedantic -Wfatal-errors && ./a.exe
> 0.0000000000000000000000000000000000000000010
> 
> $ gcc --version
> gcc (GCC) 11.1.0
> 
> # gcc on Linux
> $ gcc t903.c -Wall -Wextra -std=c11 -pedantic -Wfatal-errors && ./a.exe
> 0.0000000000000000000000000000000000000000009
> 
> # clang on Windows
> $ clang t903.c -Wall -Wextra -std=c11 -ffp-model=strict -pedantic
> -Wfatal-errors && ./a.exe
> 0.0000000000000000000000000000000000000000009
> 
> # cl on Windows
> $ cl t903.c /std:c11 /Za /fp:strict && ./t903.exe
> 0.0000000000000000000000000000000000000000009

See newlib mailing list incorrectly rounded square root thread starting:

	https://sourceware.org/pipermail/newlib/2021/018369.html

As suggested lately, I tried adding -frounding-math

	$ info gcc frounding-math

to see if it makes any difference to your test on gcc 10 and got the 
same result.
It may need to be applied to the library functions to have any useful 
impact.

I also tried Cygwin clang and got the same result.

It may be an accuracy issue or a bug in the underlying newlib printf 
conversion.

I tried fcvtbuf in the attached test program and found it does the 
rounding as expected on Cygwin:

$ gcc -o test-printf-round{,.c} && ./test-printf-round
sgn 0 decpt -42 +0.0000000000000000000000000000000000000000009 
0.0000000000000000000000000000000000000000010

-- 
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada

This email may be disturbing to some readers as it contains
too much technical detail. Reader discretion is advised.
[Data in binary units and prefixes, physical quantities in SI.]

-------------- next part --------------
/* test-printf-round.c */

#define _POSIX_SOURCE
#define _XOPEN_SOURCE	600

#include <stdio.h>
#include <stdlib.h>
#include <string.h>



#if 0
#define V		0X1.52f8a8e32e982P+140
#define V		0X0.0000000000000P+0
#endif
#define V		0X1.52f8a8e32e982P-140
#define DECIMALS	43



int
main(void)
{
    int		decpt		= 0;
    int		sgn		= -1;
    char	*b;
    static char zeros[128]	= 
	"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
    static char buf[128]	= { 0 };

    b = fcvtbuf(V, DECIMALS, &decpt, &sgn, buf);

    printf("sgn %d decpt %d %s%.*s%s%s %.*f\n",
		sgn, decpt,
		    !sgn ? "+" : 1 == sgn ? "-" : "",
			/* 0 < decpt -> decpt digits | . | buf + decpt digits */
			/* decpt < 0 -> 0. | decpt zeros | buf digits */
			decpt < 0 ? 2 : decpt,
			    decpt < 0 ? "0." : b,
				decpt < 0 ? zeros + strlen(zeros) + decpt : ".",
				    decpt < 0 ? b : b + decpt,
					DECIMALS, V);
}



More information about the Cygwin mailing list