Java-数值积分的首选方法是什么?

时间:2015-08-17 01:10:52

标签: numerical-methods numerical-integration numerical-analysis simpsons-rule

通过数值积分解决问题的首选方法是什么?

我正在寻找进行数值积分的具体功能是

integral_0^infinity (sin(s tan^(-1)(t)))/((1+t^2)^(s/2) (e^(pi t)+1)) dt 

在Wolfram中写这个显示this

Simpson的方法优于梯形方法吗? 您是否使用了发现here的Simpson 3/8规则?

这是一个深奥的主题,是否有人对特定方法有个人偏好?

我在RosettaCode中找到了以下示例 -

class NumericalIntegration
{

  interface FPFunction
  {
    double eval(double n);
  }

  public static double rectangularLeft(double a, double b, int n, FPFunction f)
  {
    return rectangular(a, b, n, f, 0);
  }

  public static double rectangularMidpoint(double a, double b, int n, FPFunction f)
  {
    return rectangular(a, b, n, f, 1);
  }

  public static double rectangularRight(double a, double b, int n, FPFunction f)
  {
    return rectangular(a, b, n, f, 2);
  }

  public static double trapezium(double a, double b, int n, FPFunction f)
  {
    double range = checkParamsGetRange(a, b, n);
    double nFloat = (double)n;
    double sum = 0.0;
    for (int i = 1; i < n; i++)
    {
      double x = a + range * (double)i / nFloat;
      sum += f.eval(x);
    }
    sum += (f.eval(a) + f.eval(b)) / 2.0;
    return sum * range / nFloat;
  }

  public static double simpsons(double a, double b, int n, FPFunction f)
  {
    double range = checkParamsGetRange(a, b, n);
    double nFloat = (double)n;
    double sum1 = f.eval(a + range / (nFloat * 2.0));
    double sum2 = 0.0;
    for (int i = 1; i < n; i++)
    {
      double x1 = a + range * ((double)i + 0.5) / nFloat;
      sum1 += f.eval(x1);
      double x2 = a + range * (double)i / nFloat;
      sum2 += f.eval(x2);
    }
    return (f.eval(a) + f.eval(b) + sum1 * 4.0 + sum2 * 2.0) * range / (nFloat * 6.0);
  }

  private static double rectangular(double a, double b, int n, FPFunction f, int mode)
  {
    double range = checkParamsGetRange(a, b, n);
    double modeOffset = (double)mode / 2.0;
    double nFloat = (double)n;
    double sum = 0.0;
    for (int i = 0; i < n; i++)
    {
      double x = a + range * ((double)i + modeOffset) / nFloat;
      sum += f.eval(x);
    }
    return sum * range / nFloat;
  }

  private static double checkParamsGetRange(double a, double b, int n)
  {
    if (n <= 0)
      throw new IllegalArgumentException("Invalid value of n");
    double range = b - a;
    if (range <= 0)
      throw new IllegalArgumentException("Invalid range");
    return range;
  }


  private static void testFunction(String fname, double a, double b, int n, FPFunction f)
  {
    System.out.println("Testing function \"" + fname + "\", a=" + a + ", b=" + b + ", n=" + n);
    System.out.println("rectangularLeft: " + rectangularLeft(a, b, n, f));
    System.out.println("rectangularMidpoint: " + rectangularMidpoint(a, b, n, f));
    System.out.println("rectangularRight: " + rectangularRight(a, b, n, f));
    System.out.println("trapezium: " + trapezium(a, b, n, f));
    System.out.println("simpsons: " + simpsons(a, b, n, f));
    System.out.println();
    return;
  }

  public static void main(String[] args)
  {
    testFunction("x^3", 0.0, 1.0, 100, new FPFunction() {
        public double eval(double n) {
          return n * n * n;
        }
      }
    );

    testFunction("1/x", 1.0, 100.0, 1000, new FPFunction() {
        public double eval(double n) {
          return 1.0 / n;
        }
      }
    );

    testFunction("x", 0.0, 5000.0, 5000000, new FPFunction() {
        public double eval(double n) {
          return n;
        }
      }
    );

    testFunction("x", 0.0, 6000.0, 6000000, new FPFunction() {
        public double eval(double n) {
          return n;
        }
      }
    );

    return;
  }
}

我写了一个梯形方法的变体。我希望改进这一点,以便更准确。

    public class AbelMain {
    public static void main(String[] args) {
        AbelMain();
        //System.out.println(Math.pow(1.92, -77));
    }

    public static void AbelMain() {
        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("Please enter a valid number for s.");
        }
        start = System.currentTimeMillis();
        System.out.println("The value for Zeta(s) is " + AbelPlana(s));
        stop = System.currentTimeMillis();
        totalTime = (double) (stop-start) / 1000.0;
        System.out.println("Total time taken is " + totalTime + " seconds.");
    }

    // The definite integral for Zeta(s) in the Abel Plana formula.
    // Numerator = Sin(s * arctan(t))
    // Denominator = (1 + t^2)^(s/2) * (e^(pi*t) + 1)
    public static double function(double x, double s) {
         double num = Math.sin(s * Math.atan(x));
        double den = Math.pow((1.0 + Math.pow(x, 2.0)), s / 2.0) *
                        (Math.pow(Math.E, Math.PI * x) + 1.0);
        return num / den;
    }

    // Evaulates the integral through the Trapezoidal Method.
    // The integral starts at a and ends at b.
    // A third parameter is introduced for the step size
    static double trapIntegrate(double a, double b, int step, double s) {
      double dx = (b - a) / step;              // step size
      double sum = 0.5 * (function(a, s) + function(b, s));    // area
      for (int i = 1; i < step; i++) {
         double x = a + dx * i;
         sum = sum + function(x, s);
      }

      return sum * dx;
   }


    // Returns an approximate sum of Zeta(s) through Simpson's rule.
    public static double AbelPlana(double s) {
        double C1 = Math.pow(2.0, s - 1.0) / (s - 1.0);
        double C2 = Math.pow(2.0, s);
        return C1 - C2 *trapIntegrate(0, 100, 1000, s);
    }
}

0 个答案:

没有答案