Thursday, April 23, 2009

Negative zero in Java

Knut made a posting on the Derby list which caught my attention. He was investigating DERBY-2447, which is a lingering intermittent bug in the Derby regression tests that produces the signature: "expected [0.0] but was [-0.0]"

Knut noticed that Derby's NumberDataType has a very interesting bit of code which is designed to convert negative zero to positive zero:

// Normalize negative floats to be "positive" (can't detect easily without using Float object because -0.0f = 0.0f)
if (v == 0.0f) v = 0.0f;

That is certainly an interesting line of code!

The point of this code is that the "if" statement should evaluate to true in two situations:
  1. When "v" is zero.
  2. When "v" is negative zero.
In either case, the if statement should be true, and the variable should be reset to ordinary zero.

Knut is wondering whether certain compilers might see that line and optimize it entirely away, because the compiler thinks that the statement would have no effect (not understanding that the statement could be true when v was negative zero).

It seems like the line of code could also be phrased as:

if (v == -0.0f) v = 0.0f;

In this case, it might be more obvious that the statement's intent is to transform negative zero into positive zero (it would also presumably transform positive zero into positive zero, just as the current statement does, but that's fine).

Optimizing compilers are fascinating creatures. In my "work life", I maintain a small library of software which implements an object-relational API over various relational databases. Part of that library provides a small O/R query language. In the query language, we currently do NOT perform any sort of optimization; we crudely translate the user's query into a corresponding SQL query, and then we let the DBMS consider the query.

Our assumption is that the DBMS is much better at optimizing than we are, partly because I'm just one programmer and DBMS companies have huge staffs, but also partly because at the level of my library, I have only limited information available about the objects referred to by the query, while the DBMS has much more information about tables, columns, views, indexes, etc.

Java language compilers are a whole different world than DBMS query language compilers, of course, but some of the principles are similar:
  • common sub-expression elimination
  • short-circuiting intermediate results
  • considering alternate implementations, and choosing the most efficient
I wonder what actual part of the compiler's internals are handling this line of code. It might even be that it's not the compiler, but rather some runtime behavior (such as just-in-time compilation, or JITing, which is another source of Java complexity).

1 comment:

  1. Does negative 0 cause problems somehow? Why convert it? I accidentally used a -0 in my code and it made me wonder if it had any effect in any use cases(Which is how I find myself in your blog)?