21

I thought that result of any mathematical operation on a NaN should give me a NaN back, but Math.round(Float.NaN) == 0

What is the rationale for such behavior of Math.round()?

Curiously, C# behaves differently: http://msdn.microsoft.com/en-us/library/75ks3aby.aspx

MK.
  • 33,605
  • 18
  • 74
  • 111
  • as @pst has said, its the normal behavior defined for NaN: "If the argument is NaN, the result is 0". – Luiggi Mendoza Apr 12 '12 at 03:55
  • The rationale is that there used to be a bug in `Math.round()` when called on NaN it could potentially ruin future calls to `Math.round()`: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4755500 – Hunter McMillen Apr 12 '12 at 03:58
  • 2
    The difference is likely to be; in Java it returns `long` which cannot be `Double.NaN` whereas an C# it returns a `double` – Peter Lawrey Apr 12 '12 at 06:02

2 Answers2

28

Math.round() is defined as (long)Math.floor(a + 0.5d).

  1. If a is NaN, then a+0.5d is NaN.
  2. Math.floor() is delagated to StrictMath.floor() which returns NaN when passed in NaN.
  3. When casting NaN to a long, it returns 0

So ultimately, it comes down to why casting NaN to a long returns 0. This issue has been thoroughly discussed in this question.

Community
  • 1
  • 1
tskuzzy
  • 35,812
  • 14
  • 73
  • 140
  • +1 for digging into the implementation a little! Have links to the [Open Source JDK] code for the appropriate functions? –  Apr 12 '12 at 04:01
  • 6
    +1 In Java 7 this definition has been dropped due to this issue [Why Math.round(0.499999999999999917) rounds to 1 on Java 6](http://vanillajava.blogspot.co.uk/2012/04/why-mathround0499999999999999917-rounds.html) – Peter Lawrey Apr 12 '12 at 06:03
15

Haha. I want to smack myself in the head.

Math.round(double) returns a long and a long cannot be NaN. The alternative is an exception.

In C# the result is still a double.