3

I tried the following code on mac, the output is kind of strange to me.

float a = 2.225;
float b = 123.235;
printf("round: %.2f %.2f \n", a, b);
printf("round: %.2f %.2f \n", 2.225, 123.235);

output:

round: 2.22 123.24 
round: 2.23 123.23 

g++ --version

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

What are the rounding rules in printing? How I can get same printing result in these two situations? Many thanks.

Jiwei Xu
  • 31
  • 2
  • 10
    I think the difference is between `float`s and `double`s. – Fred Larson Jul 29 '16 at 14:00
  • Read http://floating-point-gui.de/ – Basile Starynkevitch Jul 29 '16 at 14:03
  • 2
    The problem is not in printing - you are getting different output because you are passing in different input. In the first case, you lose precision the moment you assign `double` values to `float` variables. – Igor Tandetnik Jul 29 '16 at 14:04
  • Take a look at http://stackoverflow.com/questions/2386772/difference-between-float-and-double. – Garf365 Jul 29 '16 at 14:04
  • 1
    And this is one of those questions where the "C/C++" tag issue strikes. There is nothing in the code that is specifically C++. Should this be re-tagged C? Should the C tag be *added*? Should there be another question asking the same thing under the "C" tag? I give up. – DevSolar Jul 29 '16 at 14:24

2 Answers2

6

The first printf() converts the float values to double and then prints the results. Note that the initializations convert the double constants to float. The second passes the double values directly. You can specify float constants with the suffix F — but the rules of C still convert those float constants to double before actually calling printf() because of default argument promotion rules.

#include <stdio.h>

int main(void)
{
    float a = 2.225;
    float b = 123.235;
    printf("round: %.2f %.2f\n", a, b);
    printf("round: %.2f %.2f\n", 2.225, 123.235);
    printf("round: %.2f %.2f\n", 2.225F, 123.235F);

    return 0;
}

Output:

round: 2.22 123.24 
round: 2.23 123.23 
round: 2.22 123.24 
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
4
2.225

That is a literal, of type double.

float a = 2.225;

That is assigning a double to a float (losing precision, see below).

printf( "%.2f", ... );

This is printing a double (even if you pass a float as parameter, due to type promotion), to a precision of two digits after the decimal point.

float a = 2.225;
printf( "%.2f", a );

This is assigning a double to a float, then casting it back to a double (type promotion), and printing that.

printf( "%.2f", 2.225 );

This is printing a double (without the back-and-forth casting).

What are the rounding rules in printing?

Rounding works as you would expect, but is not your problem here.

The difference in output happens because your a and b are float, the directly-printed literals aren't. You happen to have picked values where the loss of precision due to the cast-to-float makes a difference.

How I can get same printing result in these two situations?

Using double consistently.

double a = 2.225;
double b = 123.235;
DevSolar
  • 67,862
  • 21
  • 134
  • 209