Java Reference
In-Depth Information
tiple threads of execution (using the thread execution model in ยง17), for all possible
computational values that might be involved.
In the case of floating-point calculations, this rule applies also for infinity and not-a-num-
ber (NaN) values.
For example,
!(x<y)
may not be rewritten as
x>=y
, because these expressions have dif-
ferent values if either
x
or
y
is NaN or both are NaN.
Specifically, floating-point calculations that appear to be mathematically associative are
unlikely to be computationally associative. Such computations must not be naively re-
ordered.
For example, it is not correct for a Java compiler to rewrite
4.0*x*0.5
as
2.0*x
; while
roundoff happens not to be an issue here, there are large values of
x
for which the first
expression produces infinity (because of overflow) but the second expression pro-
duces a finite result.
So, for example, the test program:
strictfp class Test {
public static void main(String[] args) {
double d = 8e+307;
System.out.println(4.0 * d * 0.5);
System.out.println(2.0 * d);
}
}
prints:
Infinity
1.6e+308
because the first expression overflows and the second does not.
In contrast, integer addition and multiplication
are
provably associative in the Java pro-
gramming language.
For example
a+b+c
, where
a
,
b
, and
c
are local variables (this simplifying assumption
avoids issues involving multiple threads and
volatile
variables), will always produce
the same answer whether evaluated as
(a+b)+c
or
a+(b+c)
; if the expression
b+c
occurs
nearby in the code, a smart Java compiler may be able to use this common subexpres-
sion.