2015-08-08 33 views
0

在程序中,双精度转换为BigDecimal。这会返回一个非常奇怪的错误消息。Java - 将双精度转换为BigDecimal时的奇数错误消息

public static double riemannFuncForm(double s) { 
     double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)* 
      (Math.sin((Math.PI*s)/2))*gamma(1-s); 

     if(s == 1.0 || (s <= -1 && s % 2 == 0)) 
      return 0; 
     else if (s >= 0 && s < 2) 
      return getSimpsonSum(s); 
     else if (s > -1 && s < 0) 
      return term*getSimpsonSum(1-s); 
     else 
      return term*standardZeta(1-s); 
    } 

BigDecimal val = BigDecimal.valueOf(riemannFuncForm(s)); 
System.out.println("Value for the Zeta Function = " 
        + val.toEngineeringString()); 

这将返回

Exception in thread "main" java.lang.NumberFormatException 

是什么原因造成这个问题? BigDecimal.valueOf(double)无法正确工作,因为这是通过其他方法引用的?

全部程序

/************************************************************************** 
** 
** Euler-Riemann Zeta Function   
** 
************************************************************************** 
** XXXXXXXXXX 
** 06/20/2015 
** 
** This program computes the value for Zeta(s) using the standard form 
** of Zeta(s), the Riemann functional equation, and the Cauchy-Schlomilch 
** transformation. A recursive method named riemannFuncForm has been created 
** to handle computations of Zeta(s) for s < 2. Simpson's method is 
** used to approximate the definite integral calculated by the 
** Cauchy-Schlomilch transformation. 
**************************************************************************/ 

import java.util.Scanner; 
import java.math.*; 

public class ZetaMain { 

    // Main method 
    public static void main(String[] args) { 
     ZetaMain();  
    } 

    // Asks the user to input a value for s. 
    public static void ZetaMain() { 
     double s = 0; 
     double start, stop, totalTime; 
     Scanner scan = new Scanner(System.in); 
     System.out.print("Enter the value of s inside the Riemann Zeta " + 
       "Function: "); 
     try { 
       s = scan.nextDouble(); 
     } 
     catch (Exception e) { 
      System.out.println("You must enter a positive integer greater " + 
        "than 1."); 
     } 
     start = System.currentTimeMillis(); 
     if (s == 1) 
      System.out.println("The zeta function is undefined for Re(s) " + 
        "= 1."); 
     else if (s < 2) { 
      BigDecimal val = BigDecimal.valueOf(riemannFuncForm(s)); 
      System.out.println("Value for the Zeta Function = " 
        + val.toEngineeringString()); 
     } 
     else 
      System.out.println("Value for the Zeta Function = " 
        + BigDecimal.valueOf(getStandardSum(s)).toString()); 
     stop = System.currentTimeMillis(); 
     totalTime = (double) (stop-start)/1000.0; 
     System.out.println("Total time taken is " + totalTime + " seconds."); 

    } 

    // Standard form of the Zeta function. 
    public static double standardZeta(double s) { 
     int n = 1; 
     double currentSum = 0; 
     double relativeError = 1; 
     double error = 0.000001; 
     double remainder; 

     while (relativeError > error) { 
      currentSum = Math.pow(n, -s) + currentSum; 
      remainder = 1/((s-1)* Math.pow(n, (s-1))); 
      relativeError = remainder/currentSum; 
      n++; 
     } 
     System.out.println("The number of terms summed was " + n + "."); 
     return currentSum; 
    } 

    // Returns the value calculated by the Standard form of the Zeta function. 
    public static double getStandardSum(double s){ 
     return standardZeta(s); 
    } 

    // Approximation of the Gamma function through the Lanczos Approximation. 
    public static double gamma(double s){ 
        double[] p = {0.99999999999980993, 676.5203681218851, 
         -1259.1392167224028, 771.32342877765313, 
         -176.61502916214059, 12.507343278686905, 
         -0.13857109526572012, 9.9843695780195716e-6, 
         1.5056327351493116e-7}; 

        int g = 7; 

        // Implements Euler's Reflection Formula. 
        if(s < 0.5) return Math.PI/(Math.sin(Math.PI * s) 
          *gamma(1-s)); 

        s -= 1; 
        double a = p[0]; 
        double t = s + g + 0.5; 
        for(int i = 1; i < p.length; i++){ 
          a += p[i]/(s+i); 
        } 

        return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5) 
          *Math.exp(-t)*a; 
      } 

    /* Riemann's Functional Equation - Directly calculates the value of 
     Zeta(s) for s < 2. 

     1. The first if statement handles the case when s < 0 and s is a 
      multiple of 2k. These are trivial zeroes where Zeta(s) is 0. 

     2. The second if statement handles the values of 0 < s < 2. Simpson's 
      method is used to numerically compute an approximation of the 
      definite integral. 

     3. The third if statement handles the values of -1 < s < 0. Recursion 
      is used alongside an approximation through Simpson's method. 

     4. The last if statement handles the case for s <= -1 and is not a 
      trivial zero. Recursion is used directly against the standard form 
      of Zeta(s). 
    */ 
    public static double riemannFuncForm(double s) { 
     double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)* 
      (Math.sin((Math.PI*s)/2))*gamma(1-s); 

     if(s == 1.0 || (s <= -1 && s % 2 == 0)) 
      return 0; 
     else if (s >= 0 && s < 2) 
      return getSimpsonSum(s); 
     else if (s > -1 && s < 0) 
      return term*getSimpsonSum(1-s); 
     else 
      return term*standardZeta(1-s); 
    } 

    // Returns the function referenced inside the right hand side of the 
    // Cauchy-Schlomilch transformation for Zeta(s). 
    public static double function(double x, double s) { 
     double sech = 1/Math.cosh(x); // Hyperbolic cosecant 
     double squared = Math.pow(sech, 2); 
     return ((Math.pow(x, s)) * squared); 
    } 

// Simpson's rule - Approximates the definite integral of f from a to b. 
    public static double SimpsonsRule(double a, double b, double s, int n) { 
     double simpson, dx, x, sum4x, sum2x; 

     dx = (b-a)/n; 
     sum4x = 0.0; 
     sum2x = 0.0; 

     // 4/3 terms 
     for (int i = 1; i < n; i += 2) { 
      x = a + i * dx; 
      sum4x += function(x,s); 
     } 

     // 2/3 terms 
     for (int i = 2; i < n-1; i += 2) { 
      x = a + i * dx; 
      sum2x += function(x,s); 
     } 

     // Compute the integral approximation. 
     simpson = function(a,s) + function(a,b); 
     simpson = (dx/3)*(simpson + 4 * sum4x + 2 * sum2x); 
     return simpson; 
    } 

    // Handles the error for for f(x) = t^s * sech(t)^2. The integration is 
    // done from 0 to 100. 
    // Stop Simspson's Method when the relative error is less than 1 * 10^-6 
    public static double SimpsonError(double a, double b, double s, int n) 
    { 
     double futureVal; 
     double absError = 1.0; 
     double finalValueOfN; 
     double numberOfIterations = 0.0; 
     double currentVal = SimpsonsRule(a,b,s,n); 

     while (absError/currentVal > 0.000001) { 
      n = 2*n; 
      futureVal = SimpsonsRule(a,b,s,n); 
      absError = Math.abs(futureVal - currentVal)/15; 
      currentVal = futureVal; 
     } 

     // Find the number of iterations. N starts at 8 and doubles 
     // every iteration. 
     finalValueOfN = n/8; 
     while (finalValueOfN % 2 == 0) { 
      finalValueOfN = finalValueOfN/2; 
      numberOfIterations++; 
     } 
     System.out.println("The number of iterations is " 
       + numberOfIterations + "."); 
     return currentVal; 
    } 


    // Returns an approximate sum of Zeta(s) through Simpson's rule. 
    public static double getSimpsonSum(double s) { 
     double constant = Math.pow(2, (2*s)-1)/(((Math.pow(2, s)) -2)* 
       (gamma(1+s))); 
     System.out.println("Did Simpson's Method."); 
     return constant*SimpsonError(0, 100, s, 8); 
    } 
} 
+0

当你得到错误时,你输入什么值?我已经成功编译并运行了s = 3的程序。 – MockerTim

+0

由于Zeta函数的大负值。 s = -509或s = -1111。 – Axion004

+1

是你的'双'偶吗'NaN'?此外,将“double”转换为“BigDecimal”也有宝贵的一点 - 你已经失去了精确度。 –

回答

1

与你发生此错误的原因BigDecimal.valueOf(值)不接受“南”“不是数”作为参数,下面的表达式将返回NaN的

Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s) 

Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))将评估-0.0

这个功能gamma(1-s)将评估 “无限”

所以-​​0.0 *无穷大等于java中的NaN

请看这个知道Java何时能产生NaN。

When can Java produce a NaN?

+0

谢谢,看起来我需要将double转换为BigDecimal。 – Axion004

+0

我想你应该检查这个函数riemannFuncForm()是否返回NaN,然后​​你可以打印味精 –

1

我本来我所有的双重计算改变为BigDecimal的计算,以解决这一问题?

没有。你需要做的就是恰当地捕获和处理NumberFormatException。或者,在尝试转换double之前,先测试NaNInf

在这种情况下,您只使用BigDecimal进行“工程”语法格式化。所以另一种选择是直接进行格式化。 (虽然我还没有找到一个简单的方法来做到这一点)。