Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5039109

StrictMath/Math pow functions gives wrong answers for large odd integer powers

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.4.2
    • core-libs
    • x86
    • windows_2000



      Name: dk106046 Date: 04/28/2004

      OPERATING SYSTEM(S):
      Windows 2000

      FULL JDK VERSION(S):
      1.4.2_04-b05


      The StrictMath and Math pow functions give answers which contradicts the
      specification given by:
      http://java.sun.com/j2se/1.4.2/docs/api/java/lang/StrictMath.html#pow(double,%20double)
      http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#pow(double,%20double)
      If the first argument is finite and less than zero
      if the second argument is a finite even integer, the result is equal to the result of raising the absolute value of the first argument to the power of the second argument
      if the second argument is a finite odd integer, the result is equal to the negative of the result of raising the absolute value of the first argument to the power of the second argument
      if the second argument is finite and not an integer, then the result is NaN.


      The following program:

      public class pow {
          static int ln = 0;
          public static double printpow1(double a, double b) {
              double d1 = StrictMath.pow(a, b);
              double d2 = Math.pow(a, b);
              System.out.println((++ln)+" StrictMath.pow("+a+","+b+") = "+d1);
              System.out.println((++ln)+" Math.pow("+a+","+b+") = "+d2);
              return d1;
          }
          public static double printpow2(double a, double b) {
              double r = printpow1(a, b);
              double r2 = printpow1(-a, b);
              if (!Double.isInfinite(a) && !Double.isNaN(a) && a != 0.0 &&
                  !Double.isInfinite(b) && !Double.isNaN(b) &&
                  StrictMath.ceil(b) == b &&
                  StrictMath.abs(b % 2.0) == 1.0) {
                  if (Double.compare(r, -r2) != 0) System.out.println("Error");
              }
              return r;
          }
          public static double printpow3(double a, double b) {
              double r = printpow2(a, b);
              printpow2(a, -b);
              return r;
          }
          public static void main(String args[]) {
              System.out.println((++ln)+" Testing pow method");
              printpow3(1.0000000001, 10000000001.0);
              printpow3(100, 10000000001.0);
              printpow3(0.001, 10000000001.0);
          }
      }

      gives the following output
      1 Testing pow method
      2 StrictMath.pow(1.0000000001,1.0000000001E10) = 2.7182820535066154
      3 Math.pow(1.0000000001,1.0000000001E10) = 2.7182820535066154
      4 StrictMath.pow(-1.0000000001,1.0000000001E10) = -0.0
      5 Math.pow(-1.0000000001,1.0000000001E10) = -0.0
      Error
      6 StrictMath.pow(1.0000000001,-1.0000000001E10) = 0.3678794107145682
      7 Math.pow(1.0000000001,-1.0000000001E10) = 0.3678794107145682
      8 StrictMath.pow(-1.0000000001,-1.0000000001E10) = -Infinity
      9 Math.pow(-1.0000000001,-1.0000000001E10) = -Infinity
      Error
      10 StrictMath.pow(100.0,1.0000000001E10) = Infinity
      11 Math.pow(100.0,1.0000000001E10) = Infinity
      12 StrictMath.pow(-100.0,1.0000000001E10) = Infinity
      13 Math.pow(-100.0,1.0000000001E10) = Infinity
      Error
      14 StrictMath.pow(100.0,-1.0000000001E10) = 0.0
      15 Math.pow(100.0,-1.0000000001E10) = 0.0
      16 StrictMath.pow(-100.0,-1.0000000001E10) = 0.0
      17 Math.pow(-100.0,-1.0000000001E10) = 0.0
      Error
      18 StrictMath.pow(0.0010,1.0000000001E10) = 0.0
      19 Math.pow(0.0010,1.0000000001E10) = 0.0
      20 StrictMath.pow(-0.0010,1.0000000001E10) = 0.0
      21 Math.pow(-0.0010,1.0000000001E10) = 0.0
      Error
      22 StrictMath.pow(0.0010,-1.0000000001E10) = Infinity
      23 Math.pow(0.0010,-1.0000000001E10) = Infinity
      24 StrictMath.pow(-0.0010,-1.0000000001E10) = Infinity
      25 Math.pow(-0.0010,-1.0000000001E10) = Infinity
      Error

      The specification for java.lang.StrictMath also says:

      To help ensure portability of Java programs, the definitions of many of the numeric functions in this package require that they produce the same results as certain published algorithms. These algorithms are available from the well-known network library netlib as the package "Freely Distributable Math Library" (fdlibm). These algorithms, which are written in the C programming language, are then to be understood as executed with all floating-point operations following the rules of Java floating-point arithmetic.

      The network library may be found on the World Wide Web at:

         http://metalab.unc.edu/
       The Java math library is defined with respect to the version of fdlibm dated January 4, 1995. Where fdlibm provides more than one definition for a function (such as acos), use the "IEEE 754 core function" version (residing in a file whose name begins with the letter e).


      but this version of fdlibm has some bugs in the pow function (fixed in the latest version) causing the problems above.
      I think that Java should meet the special cases as defined in the Java specification, as bit for bit reproducibility of the wrong answer given by fdlibm is not very useful, so java.lang.StrictMath needs to use a fixed version of the fdlibm pow function.


      The specification for java.lang.Math says that:
      A result must be within 1 ulp of the correctly rounded result. Results must be semi-monotonic.

      The java.lang.Math results break the Java specification and there is not a contradiction in the specification, so the java.lang.Math code should also be fixed.

      ======================================================================

            darcy Joe Darcy
            dkorbel David Korbel (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: