Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the rounding rule of Java's Math.round conform to the IEEE 754 standard?

I read the IEEE754 rounding rules from wiki: https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules

And there is a example: In mode 'to nearest, ties away from zero', −12.5 should be -13.0

But java Math.round(-12.5)==-12.0.

And I'm sure Math.round not using mode 'to nearest, ties to even', because Math.round(-11.5)==-11.0

Actually, in Java Doc, it says "Returns the closest long to the argument, with ties rounding to positive infinity."

So, Java Math.round not conform to the IEEE 754 standard, is it correct?

like image 502
Eric Avatar asked Oct 24 '25 05:10

Eric


1 Answers

You are correct that Math.round does not implement any of the rounding modes described in IEEE-754. These are the ones defined in IEEE-754-2008:

  1. TiesToEven, also known as banker's rounding (2.5 -> 2, 1.5 -> 2), implemented by Math.rint
  2. TowardZero, also known as trunc, implemented in Java by casting to integer (but see footnote)
  3. TowardPositive, implemented by Math.ceil
  4. TowardNegative, implemented by Math.floor
  5. TiesToAway, rounds x.5 away from zero. This mode has no Java function but can be implemented as Math.copySign(Math.round(Math.abs(x)), x) (but see footnote)

From the descriptions, one might think that Math.round is TowardPositive but that is specifically defined as the result "[…] closest to and no less than the infinitely precise result." That is clearly not the case for Math.round, e.g. Math.round(2.3) == 2

If IEEE-754 were to define Math.round, it would be called something like TiesTowardPositive but that does not exist in the standard.

So yes, Math.round is not one of the IEEE-754 rounding modes, and also different from C/C++'s round, C#'s Math.Round, or SQL's ROUND, for example.

I cannot tell you the reason for this choice. Of course Java is free to define additional rounding functions, choose arbitrary names for all rounding functions (IEEE-754 only describes the operation, not the name), and omit some of them as they are only "shall" and "should" requirements.

Related issues that may pop up

  • Older JVMs have bugs implementing this rounding mode: Why does Math.round(0.49999999999999994) return 1?
  • The rounding in double-to-string is different from other languages, too: Why do C and Java round floats differently?

Footnote

Saying that TowardZero can be implemented by casting and that TiesToAway can be implemented via Math.round is a simplification. Since these approaches convert to integer, they fail if the floating point number exceeds the integer range. Rounding 1e200, you expect the result to be 1e200 but Math.round(1e200) will give you Long.MAX_VALUE instead. Therefore a more complete implementation of those rounding modes first has to check the value range.

like image 96
Homer512 Avatar answered Oct 26 '25 20:10

Homer512