rounding between C++ and java

I have a Dell desktop with an Intel CPU running Linux. When I write a C++ program with this line:

for (int i = 0; i < 10; i++) printf("%.1f\n", (i + .5) / 10);

I get these lines:

0.1
0.1
0.2
0.3
0.5
0.6
0.7
0.8
0.8
0.9

But if I write a java program with this line:

for (int i = 0; i < 10; i++) System.out.println(String.format("%.1f", (i + .5) / 10));

I get different results:

0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0

I realize that the CPU can't exactly represent all floating point numbers, so that 0.15 may end up to be 0.14999999999, so can round down to 0.1 instead of 0.2. But how does java always round up, while C++ will sometimes round up and sometime round down? Don't they internally end up using the same CPU instructions?
C++ produces cpu instructions. Java produces intermediate code which is interpreted when run. (A Java expert will explain this better this me...). The two are not the same.

For C++ to produce the same as Java:

 
for (int i = 0; i < 10; i++) printf("%.1f\n", round((i + .5)) / 10);


PS It seems to depend upon whether "round-half-away-from-zero" or "round-half-to-even" are used for truncation.

See https://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/

It seems that different compilers use different rounding method - so the answer could differ depending upon the used compiler.
Last edited on
to be extra clear, c++ did not round your value, printf rounded the *output*. In c++ the textual output and the actual value are frequently not the same thing at all.

consider:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main()
{	
	for (int i = 0; i < 10; i++) 
		printf("%.1f  %.5f\n", (i + .5) / 10,(i + .5) / 10);
	
}

C:\c>a
0.1  0.05000
0.1  0.15000
0.2  0.25000
0.3  0.35000
0.5  0.45000
0.6  0.55000
0.7  0.65000
0.8  0.75000
0.8  0.85000
0.9  0.95000


I mean this is just screwy. .75 is .8 but .85 isnt .9 ?

throwing in another wrench, using c++ output instead of C:
cout << setprecision(1) << (i + .5) / 10 << endl;
0.05
0.1
0.2
0.3
0.5
0.6
0.7
0.8
0.8
0.9

and doing it more carefully,
looping over printf("%.1f\n", round((i + .5))/10.0);

0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0

cout of the above is identical numerically and the 1.0 is 1 instead is the only change on my system. I prefer C's output for floating point values, as it is easier to control most of the time.


The 'careful' way is a big lesson in c++. You have to be very aware of floating point behavior and write your code so that it does what you want in c++, the compiler does not guess what you want or try to do anything for you. It would be nice if the output / stringify tools could do a standard human round to a decimal place, but if you want that, you have to write it yourself.
Last edited on
@jonnin, you need to also use "fixed" mode to duplicate the printf output.

@OP, try this in Java and see if you get the same as the C++ results:
https://en.wikipedia.org/wiki/Strictfp
It looks like you can add it to a whole class to enforce "strict fp" in that class.
Topic archived. No new replies allowed.