1

我正在使用“think java”这本书,我被困在练习 7.6 上。这里的目标是编写一个可以找到. 它给了你一些提示:

一种评估方法是使用无限级数展开:

换句话说,我们需要将一系列项相加,其中第 i 项等于

这是我想出的代码,但对于除 1 的幂之外的任何内容,它都是非常错误的(与 Math.exp 相比)。我不明白为什么,据我所知,代码是正确的书中的公式。我不确定这是否更像是一个数学问题,或者与 double 和 int 可以容纳多大的数字有关,但我只是想了解为什么这不起作用。

   public static void main(String[] args) {
      System.out.println("Find exp(-x^2)");
      double x = inDouble("Enter x: ");
      System.out.println("myexp(" + -x*x + ") = " + gauss(x, 20));
      System.out.println("Math.exp(" + -x*x + ") = " + Math.exp(-x*x));
   }

   public static double gauss(double x, int n) {
      x = -x*x;
      System.out.println(x);
      double exp = 1;
      double prevnum = 1;
      int prevdenom = 1;
      int i = 1;
      while (i < n) {
         exp = exp + (prevnum*x)/(prevdenom*i);
         prevnum = prevnum*x;
         prevdenom = prevdenom*i;
         i++;
      }
      return exp;
   } // I can't figure out why this is so inacurate, as far as I can tell the math is accurate to what the book says the formula is

   public static double inDouble(String string) {
      Scanner in = new Scanner (System.in);
      System.out.print(string);
      return in.nextDouble();
   }
4

1 回答 1

1

我即将添加对您问题的评论。我这样做是因为我觉得我有一个更好的实现。

你的方法

您的方法是让函数接受两个参数,其中第二个参数是迭代次数。这还不错,但是正如@JamesKPolk 指出的那样,您可能需要手动搜索不会溢出的 int (或 long )

我的方法

我的方法将使用一种称为机器 epsilon 的数据类型。机器 epsilon 是可表示为该数字的该类型的最小数字(在您的情况下为双精度数)。如果“不允许”您在课堂上访问机器 epsilon,则存在用于确定机器 epsilon 是什么的算法。Double

这背后有数学:

您的函数的系列表示是e^(-x^2) 的系列表示 因为它是交替系列,所以误差项是您选择不包括的第一项的绝对值(我将证明留给您)。

这意味着我们可以有一个不使用迭代的基于错误的实现!最好的部分是您可以为浮点数和“超过”双精度的数据类型实现它!我这样介绍:

public static double gauss(double x) 
{
    x = -x*x;
    double exp = 0, error = 1, numerator = 1, denominator = 1;
    double machineEpsilon = 1.0;
    // calculate machineEpsilon
    while ((1.0 + 0.5 * machineEpsilon) != 1.0)
        machineEpsilon = 0.5 * machineEpsilon;
    int n = 0; //
    // while the error is large enough to be representable in terms of the current data type
    while ((error >= machineEpsilon) || (-error <= -machineEpsilon))
    {
        exp += error;
        // calculate the numerator (it is 1 if we just start, but -x times its past value otherwise)
        numerator = ((n == 0) ? 1 : -numerator * x);
        // calculate the denominator (denominator gets multiplied by n)
        denominator *= (n++);
        // calculate error
        error = numerator/denominator;
    }
    return exp;
}

让我知道这是如何工作的!

于 2015-10-03T20:39:22.717 回答