c language, When decimal digit of %g in printf equal to 0.5, and length is more than 6, it is not upper ceil, why?

144 Views Asked by At

Here is my program:

#include <stdio.h>

int main()
{
    printf("%g\n", 100000.5);
    printf("%g\n", 100001.5);
    printf("%g\n", 100002.5);
    printf("%g\n", 100003.5);
    printf("%g\n", 100004.5);
    printf("%g\n", 100005.5);
    return 0;
}

I am getting this output using gcc:

100000  
100002  
100002  
100004   
100004  
100006

In VS2019, I get different output which looks more consistent:

100001  
100002  
100003  
100004   
100005  
100006

Why does the output differ? Is it about compiler?

1

There are 1 best solutions below

0
David Ranieri On

Is it about compiler?

Yes, IEEE 754 defines four possible rounding modes, quoted from the gcc man pages:

Round to nearest. This is the default mode. It should be used unless there is a specific need for one of the others. In this mode results are rounded to the nearest representable value. If the result is midway between two representable values, the even representable is chosen. Even here means the lowest-order bit is zero. This rounding mode prevents statistical bias and guarantees numeric stability: round-off errors in a lengthy calculation will remain smaller than half of FLT_EPSILON.

Round toward plus Infinity. All results are rounded to the smallest representable value which is greater than the result.

Round toward minus Infinity. All results are rounded to the largest representable value which is less than the result.

Round toward zero. All results are rounded to the largest representable value whose magnitude is less than that of the result. In other words, if the result is negative it is rounded up; if it is positive, it is rounded down.

Therefore gcc uses "Round to nearest" while Visual Studio uses "Round toward plus Infinity"

The good news is that you can change the mode:

fenv.h defines constants which you can use to refer to the various rounding modes. Each one will be defined if and only if the FPU supports the corresponding rounding mode.

In your case:

#include <stdio.h>
#include <fenv.h>
                                                                                                                                             
int main(void)
{
    fesetround(FE_UPWARD);
    printf("%g\n", 100000.5);
    printf("%g\n", 100001.5);
    printf("%g\n", 100002.5);
    printf("%g\n", 100003.5);
    printf("%g\n", 100004.5);
    printf("%g\n", 100005.5);
    return 0;
}