计算辛普森规则错误 < 10^-6
Calculating simpsons Rule error < 10^-6
我正在尝试计算辛普森规则以获得 < 10^-6 的准确度。但是每当函数运行时,由于 0/sin(0),我都会得到 NaN 或 DNE 错误。当我 =1 时,如何解决这个错误? **编辑我的函数以包含当我 == 1 时。
public static double simpsonsRuleFunction1(double valueN, double valueA, double valueB, double valueDx) {
double e = 0.0;
double simpsonsRule = 0.0;
double valueHolder = 0.0;
valueN = 2;
valueA = 0;
valueB = (Math.PI)/2;
for(int i = 1; i<=valueN+1 ; i++){
valueDx = (valueB-valueA)/valueN;
e = valueA + ((i-1)*valueDx);
if (i==1) {
// Limit as x -> 0
simpsonsRule += Math.pow(10,-10);
}
else if ((i % 2 == 0) && ( i > 1) && (i < valueN+1 )) {
simpsonsRule += 4*(e/((Math.sin(e))));
}
else if ((i % 2 != 0) && ( i > 1) && (i < valueN+1 )) {
simpsonsRule += 2*(e/((Math.sin(e))));
}
else if (i == valueN+1 ) {
simpsonsRule += (e/((Math.sin(e))));
}
}
simpsonsRule = simpsonsRule *((valueDx)/3);
while(Math.abs(valueHolder - simpsonsRule) > Math.pow(10,-6)) {
System.out.println("\nValueHolder" + valueHolder);
valueHolder = simpsonsRule;
valueN +=2;
valueDx = (valueB-valueA)/valueN;
simpsonsRule = 0;
for(int i = 1; i<=valueN + 1; i++){
e = valueA + ((i-1)*valueDx);
if (i==1) {
// Limit as x -> 0
simpsonsRule += Math.pow(10,-10);
}
else if (i % 2 == 0) {
simpsonsRule += 4*(e/((Math.sin(e))));
}
else if ((i % 2 != 0) && ( i > 1) && (i < valueN + 1)) {
simpsonsRule += 2*(e/((Math.sin(e))));
}
else if (i == valueN + 1) {
simpsonsRule += (e/((Math.sin(e))));
}
}
simpsonsRule = simpsonsRule *((valueDx)/3);
}
return valueN;
}
您需要明确处理 e==0
的情况。
我建议拉出一个函数,这样你就不用重复逻辑了:
double f(e) {
return e==0 ? 1 : e/Math.sin(e);
}
然后在任何需要计算函数的地方使用它,例如
simpsonsRule += 4*(e/((Math.sin(e))));
变成
simpsonsRule += 4*f(e);
当然,您可能还需要处理 +/- N pi
处的情况,具体取决于您允许的输入值。
根据 pcarter 的建议进行编辑:您可能希望使用一个非零阈值,在该阈值以下使用 1 作为函数值,以处理零附近的数值误差,例如
return (Math.abs(e) < 1e-10) ? 1 : e/Math.sin(e);
选择阈值(在本例中为 1e-10
)以提供足够准确的结果。
我正在尝试计算辛普森规则以获得 < 10^-6 的准确度。但是每当函数运行时,由于 0/sin(0),我都会得到 NaN 或 DNE 错误。当我 =1 时,如何解决这个错误? **编辑我的函数以包含当我 == 1 时。
public static double simpsonsRuleFunction1(double valueN, double valueA, double valueB, double valueDx) {
double e = 0.0;
double simpsonsRule = 0.0;
double valueHolder = 0.0;
valueN = 2;
valueA = 0;
valueB = (Math.PI)/2;
for(int i = 1; i<=valueN+1 ; i++){
valueDx = (valueB-valueA)/valueN;
e = valueA + ((i-1)*valueDx);
if (i==1) {
// Limit as x -> 0
simpsonsRule += Math.pow(10,-10);
}
else if ((i % 2 == 0) && ( i > 1) && (i < valueN+1 )) {
simpsonsRule += 4*(e/((Math.sin(e))));
}
else if ((i % 2 != 0) && ( i > 1) && (i < valueN+1 )) {
simpsonsRule += 2*(e/((Math.sin(e))));
}
else if (i == valueN+1 ) {
simpsonsRule += (e/((Math.sin(e))));
}
}
simpsonsRule = simpsonsRule *((valueDx)/3);
while(Math.abs(valueHolder - simpsonsRule) > Math.pow(10,-6)) {
System.out.println("\nValueHolder" + valueHolder);
valueHolder = simpsonsRule;
valueN +=2;
valueDx = (valueB-valueA)/valueN;
simpsonsRule = 0;
for(int i = 1; i<=valueN + 1; i++){
e = valueA + ((i-1)*valueDx);
if (i==1) {
// Limit as x -> 0
simpsonsRule += Math.pow(10,-10);
}
else if (i % 2 == 0) {
simpsonsRule += 4*(e/((Math.sin(e))));
}
else if ((i % 2 != 0) && ( i > 1) && (i < valueN + 1)) {
simpsonsRule += 2*(e/((Math.sin(e))));
}
else if (i == valueN + 1) {
simpsonsRule += (e/((Math.sin(e))));
}
}
simpsonsRule = simpsonsRule *((valueDx)/3);
}
return valueN;
}
您需要明确处理 e==0
的情况。
我建议拉出一个函数,这样你就不用重复逻辑了:
double f(e) {
return e==0 ? 1 : e/Math.sin(e);
}
然后在任何需要计算函数的地方使用它,例如
simpsonsRule += 4*(e/((Math.sin(e))));
变成
simpsonsRule += 4*f(e);
当然,您可能还需要处理 +/- N pi
处的情况,具体取决于您允许的输入值。
根据 pcarter 的建议进行编辑:您可能希望使用一个非零阈值,在该阈值以下使用 1 作为函数值,以处理零附近的数值误差,例如
return (Math.abs(e) < 1e-10) ? 1 : e/Math.sin(e);
选择阈值(在本例中为 1e-10
)以提供足够准确的结果。