Unexpected NaN from arithmetic operation with double
Unexpected NaN from arithmetic operation with double
I抦 not sure if this is the right place to post this message but I hope someone can help. I'm puzzled by a very strange computational error. Java is multiplying two doubles (a[2]*b[2] or 0.0 * 0.0) and is getting NaN. I've attached the code snippet below.
Does anyone have any suggestions on how I would get to the bottom of this issue? The types involved are all double. The values are originally created from Double.parseDouble(String) and stored in arrays of double. I have already tried several things. I抳e added the key word strictfp in the method declaration. I抳e also tried making the whole class strictfp and final. It causes the issue to occur less but still didn't work. The code snippet below shows only one case where a computational error occurs but all cases seem to occur during a basic arithmetic operation (division or multiplication). I though it could be a multi-thread issue so I made a copy of "a" and passed it to scalarProduct but that still didn't solve the issue. I抦 running my application as an applet with j2re1.4.1._05 on the client machine. I抳e upgraded to j2re1.4.2_08 and haven抰 noticed the issue again. Could j2re1.4.1_05 be the problem? I haven抰 seen any posting that reports a defect relating to this issue. I would switch to the newer version but I really need it to run on j2re1.4.1_05. Suggestions?
-binh
[1423 byte] By [
Ben_Pha] at [2007-11-30]

Mulipying 0.0 with infinity will produce an NaN outcome. Like this:
double a = 0.0;
double b = Double.POSITIVE_INFINITY;
System.out.println(a*b);
More info can be found here: http://www.concentric.net/~Ttwang/tech/javafloat.htm
Good luck.
forgot to add the code snippet in my original posting.
Code:
public static double length(double[] a)
{
System.out.println("a=["+a[0]+", "+a[1]+", "+a[2]+"]");
double x = scalarProduct(a, a);
double len = Math.sqrt(x);
System.out.println("scalarProduct(a, a)="+x+"; len="+len); ...
}
public static double scalarProduct(double[] a, double[] b)
{
double sp = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
double x = a[0] * b[0];
double y = a[1] * b[1];
double z = a[2] * b[2];
System.out.println("sp="+sp
+", a[0]*b[0]="+a[0] * b[0]+", "+x
+", a[1]*b[1]="+a[1] * b[1]+", "+y
+", a[2]*b[2]="+a[2] * b[2]+", "+z
+", x+y+z="+(a[0] * b[0] + a[1] * b[1] + a[2] * b[2]));
return (sp);
}
OutPut:
a=[0.0, -1.0, 0.0]
sp=NaN, a[0]*b[0]=0.0, 0.0, a[1]*b[1]=1.0, 1.0, a[2]*b[2]=0.0, NaN, x+y+z=NaN scalarProduct(a, a)=NaN; len=NaN sp=1.0, a[0]*b[0]=0.0, 0.0, a[1]*b[1]=1.0, 1.0, a[2]*b[2]=0.0, 0.0, x+y+z=1.0 scalarProduct(a, a)=1.0
thanks for the reply.Yes, your statement is true. Unfortunately, in my case, both values were 0.0. At least that's what was observed with println() and with the debugger. regards,Binh
> thanks for the reply.Yes, your statement is true.
> Unfortunately, in my case, both values were 0.0. At
> t least that's what was observed with println() and
> with the debugger.
>
> regards,
>
> Binh
Is that all your code? That can't produce a NaN output for all I know. I tested your two methods with the same input and this is what I got:
a=[0.0, -1.0, 0.0]
sp=1.0, a[0]*b[0]=0.0, 0.0, a[1]*b[1]=1.0, 1.0, a[2]*b[2]=0.0, 0.0, x+y+z=1.0
scalarProduct(a, a)=1.0; len=1.0
The strange thing is that it doesn抰 occur all time. The application that I抦 working with does a lot of mathematical computation relating to imaging. I have only been able to force it to happen by repeating a particular step with the application. I抳e been making modification in an attempt to debug this issue. I抳e used the RAD6 debugger to trace it down to the scalarProduct() method and sometimes the vectorProduct() method. It does not occur every time and in the same code but every time I trace it down it always comes down to an arithmetic operation that resulted in a NaN. The arguments were valid as far as I can determine. I抦 looking for different debugging tools or methods if anybody can suggest some. The original code looks more like this
public class VectorCalculus
{
private VectorCalculus() {}
?br>
public static double[] vectorProduct(double[] a, double[] b)
{
double[] result = new double[3];
result[0] = a[1] * b[2] - a[2] * b[1];
result[1] = a[2] * b[0] - a[0] * b[2];
result[2] = a[0] * b[1] - a[1] * b[0];
return (result);
}
public static double scalarProduct(double[] a, double[] b)
{
return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
}
public static double length(double[] a)
{
return (Math.sqrt(scalarProduct(a, a)));
}
?
If you cleaned up your output a little it would be a lot easier to read the debugging.
OutPut:
a=[0.0, -1.0, 0.0]
sp=NaN
a[0]*b[0]=0.0, 0.0
a[1]*b[1]=1.0, 1.0
a[2]*b[2]=0.0, NaN
x+y+z=NaN
Why aren't you printing out the values in b[]? I guess it's because you are passing in the same array twice. I can't see how you would get two different values in the marked line above.
You say you make a copy of, I'll assume that you are doing this correctly (using arrayCopy or a loop). If it's not a multithreading problem, then there's gotta be a bug to produce that output. The next thing to do would be to javap the class and see if there's anything fishy there.
I do recall some issues with JIT that caused similarly puzzling issues in the early 1.4 versions. Are you sure you can't upgrade? You might not have a choice.
It would be fairly easy for the vector product to produce NAN, and of course once propagated, everything down stream would fail as well
your vector product involves the difference ot two products. If the products overflow they become infinities and then the difference of two infinities of the same sign is NAN
your scalar product code can fail for the same basic reason, adding different signed infinities.
However the length code should not fail because the signs should all be positive.
Humor me and rewrite your length.
double length(double[] a);
double a1 = a[1];
double a2 = a[2];
double a3 = a[3];
double sum = a1*a1 + a2*a2 + a3*a3;
double res = Math.sqrt(sum);
if( new Double(res).isNaN()){
System.out.println("a[1] = " + a[1]);
System.out.println("a[2] = " + a[2]);
System.out.println("a[3] = " + a[3]);
System.out.println("a1 = " + a1);
System.out.println("a2 = " + a2);
System.out.println("a3 = " + a3);
}