2

I would like to calculate (1.0-p)^n where p is a double between 0 and 1 (often very close to 0) and n is a positive integer that might be on the order of hundreds or thousands (perhaps larger; I'm not sure yet). If possible I would love to just use Java's built in java.lang.Math.pow(1.0-p, n) for this, but I'm slightly concerned that there might be a gigantic loss of accuracy/precision in doing so with the range of values that I'm interested in. Does anybody have a rough idea of what kind of error I might expect using Java's implementation? I'm not sure what goes on under the hood in their implementation (logs and/or Taylor approximations?), so I can't hazard a good guess.

I'm mostly concerned about relative error (i.e. not being off by more than an order of magnitude). If the answer turns out to be that Java's implementation will produce too much error, do you have any good library recommendations (but again, I'm hoping this shouldn't be needed)? Thanks.

Michael McGowan
  • 6,528
  • 8
  • 42
  • 70

3 Answers3

4

According to the API doc:

The computed result must be within 1 ulp of the exact result.

So I don't think you need to worry about the implementation so much as about the limits of floating-point accuracy. You may want to consider using BigDecimal.pow() if accuracy rather than performance is your primary concern.

mikera
  • 105,238
  • 25
  • 256
  • 415
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • I actually checked the Javadoc and yet I somehow missed that line, thanks. As for `BigDecimal`, I had ruled that out before I realized that `n` was an integer. I think that would work also. – Michael McGowan Apr 05 '11 at 21:35
0

You can take a look at the java.land.Math class source file and see if you can understand the exact method. Here is the link, http://www.docjar.com/html/api/java/lang/Math.java.html.

Zorayr
  • 23,770
  • 8
  • 136
  • 129
  • I tried that, but it eventually resorts to native code and I didn't know where to go from there. – Michael McGowan Apr 05 '11 at 21:25
  • How about you try to use Java StrictMath class - http://download.oracle.com/javase/1.4.2/docs/api/java/lang/StrictMath.html. I believe the algorithms are much better defined in the documentation (or at least name the alg. used so you can look it up). – Zorayr Apr 06 '11 at 22:40
  • @Michael McGowan The implementation of the native java.lang.Math code can be found at ftp://ftp.netlib.org/fdlibm.tar – Christopher Jul 21 '11 at 05:33
-1

Some empirical results:

public static void main(String[] args)
{
    double e = 0.000000000001d;
    System.out.println(Math.pow(1-e, 1.0d/e));
    float f =  0.000001f;
    System.out.println(Math.pow(1-f, 1.0f/f));
}

0.36788757938730976
0.3630264891374932

Both should converge to 1/e (0.36787944....) so obviously float is out of the question but double might have enough precision for you.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
  • 3
    This isn't measuring the accuracy of `pow( )`; it's measuring the accuracy of evaluating an expression containing `pow( )` as well as floating-point representation, subtraction, and division. Even if `pow( )` were perfectly accurate, the result of this computation would not be precisely equal to 1/e (nor does the value of this expression go to 1/e as the argument goes to zero when evaluated in "ideal" floating-point arithmetic). – Stephen Canon Apr 05 '11 at 21:58