如何创建 Exp(-x^2) 函数?
how to create an Exp(-x^2) function?
我正在使用 "think java" 这本书,但我被困在练习 7.6 上。这里的目标是编写一个可以找到
的函数。它给你一些提示:
One way to evaluate is
to use the infinite series expansion:

In other words, we need to add up a series of terms where the ith term
is equal to

这是我想出的代码,但是除了 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();
}
我即将添加对您问题的评论。我这样做是因为我觉得我的实现稍微好一点。
你的方法
您的方法是让函数接受两个参数,其中第二个参数是迭代次数。这还不错,但正如@JamesKPolk 指出的那样,您可能需要手动搜索不会溢出的 int(或 long)
我的做法
我的方法将使用称为机器 epsilon 的数据类型。机器 epsilon 是可表示为该数字的该类型的最小数字(在您的情况下为双精度)。存在 algorithm 用于确定该机器 epsilon 是什么,如果您不 "allowed" 访问 Double
class.
中的机器 epsilon
这背后有数学:
您的函数的级数表示是
由于它是交替系列,误差项是您选择不包括的第一项的绝对值(我将证明留给您)。
这意味着我们可以有一个不使用迭代的基于错误的实现!最好的部分是您可以为浮点数和 "more" 比双倍的数据类型实现它!我这样介绍:
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;
}
告诉我这是怎么回事!
我正在使用 "think java" 这本书,但我被困在练习 7.6 上。这里的目标是编写一个可以找到 的函数。它给你一些提示:
One way to evaluate is to use the infinite series expansion:
In other words, we need to add up a series of terms where the ith term is equal to
这是我想出的代码,但是除了 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();
}
我即将添加对您问题的评论。我这样做是因为我觉得我的实现稍微好一点。
你的方法
您的方法是让函数接受两个参数,其中第二个参数是迭代次数。这还不错,但正如@JamesKPolk 指出的那样,您可能需要手动搜索不会溢出的 int(或 long)
我的做法
我的方法将使用称为机器 epsilon 的数据类型。机器 epsilon 是可表示为该数字的该类型的最小数字(在您的情况下为双精度)。存在 algorithm 用于确定该机器 epsilon 是什么,如果您不 "allowed" 访问 Double
class.
这背后有数学:
您的函数的级数表示是
这意味着我们可以有一个不使用迭代的基于错误的实现!最好的部分是您可以为浮点数和 "more" 比双倍的数据类型实现它!我这样介绍:
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;
}
告诉我这是怎么回事!