我的辛普森法则计算器是否正确 (java)?
Is my Simpson's rule calculator correct (java)?
我应该计算
使用 Simpson 规则,有 4 个子区间。
我当然不想手工完成,所以我尝试在 Java 中编写该算法。
辛普森法则的公式是
这是我的代码:
import java.util.Scanner;
import java.util.Locale;
public class Simpson {
public static void main(String[] args) {
Scanner input = new Scanner(System.in).useLocale(Locale.US);
//e= 2.718281828459045 to copy paste
System.out.println("Interval a: ");
double aInt = input.nextDouble();
System.out.println("Interval b: ");
double bInt = input.nextDouble();
System.out.println("How many sub intervals: ");
double teilInt = input.nextDouble();
double intervaldistance = (bInt-aInt)/teilInt;
System.out.println("h = "+"("+bInt+"-"+aInt+") / "+teilInt+ " = "+intervaldistance);
double total = 0;
System.out.println("");
double totalSum=0;
for(double i=0; i<teilInt; i++) {
bInt = aInt+intervaldistance;
printInterval(aInt, bInt);
total = prod1(aInt, bInt);
total = total*prod2(aInt, bInt);
aInt = bInt;
System.out.println(total);
totalSum=totalSum+total;
total=0;
}
System.out.println("");
System.out.println("Result: "+totalSum);
}
static double prod1(double a, double b) { // first product of simpson rule; (b-a) / 6
double res1 = (b-a)/6;
return res1;
}
static double prod2(double a, double b) { // second pproduct of simpson rule
double res2 = Math.log(a)+4*Math.log((a+b)/2)+Math.log(b);
return res2;
}
static void printInterval(double a, double b) {
System.out.println("");
System.out.println("["+a+"; "+b+"]");
}
}
Output for 4 sub intervals:
[1.0; 1.4295704571147612]
0.08130646125926948
[1.4295704571147612; 1.8591409142295223]
0.21241421690076787
[1.8591409142295223; 2.2887113713442835]
0.31257532785558795
[2.2887113713442835; 2.7182818284590446]
0.39368288949073565
Result: 0.9999788955063609
现在,如果我将我的解决方案与其他在线计算器 (http://www.emathhelp.net/calculators/calculus-2/simpsons-rule-calculator/?f=ln+%28x%29&a=1&b=e&n=4&steps=on) 进行比较,它会有所不同。但我不明白为什么我的应该是错误的。
我的方案是0.9999788955063609
,网上的方案是0.999707944567103
可能是我弄错了?但是我已经仔细检查了所有内容,但找不到。
您可能通过多次执行 b_n = a_{n} + interval 来累积舍入误差。
相反,您可以使用归纳法,其中您说 a_n = a_0 + n*interval,因为这只涉及引入一次舍入误差。
我会用实际数字进行测试,以确认并稍微充实答案,但同时您可以观看handmade hero
关于误差累积的解释
PS。作为奖励,您可以观看手工英雄的节选!
更新:我看过你的link。虽然我上面描述的问题 确实 适用,但精度差异很小(您将得到答案 0.9999788955063612)。您的情况出现差异的原因是在线计算器中使用的公式在符号方面略有不同,它将区间 [a,b] 视为 2h。也就是说,你的4个区间相当于他们计算的8个区间。
如果您在该网页中放置 8 个矩形,您将获得与此处(更准确)数字相同的结果:
Answer: 0.999978895506362.
查看该网页上使用的符号的更好解释 here
我将您的增量计算更改为顶部,这样您就不会一遍又一遍地计算增量。您也没有为奇数和偶数因素应用正确的乘数,也没有为 deltaX 应用正确的公式,因为它必须是:((a-b)/n) /3
double deltaX = ((bInt-aInt)/teilInt)/3;
for(int i=0; i<=teilInt; i++) { //changed to <= to include the last interval
bInt = aInt+intervaldistance;
printInterval(aInt, bInt);
total = prod2(aInt, bInt, i+1, teilInt); //added the current interval and n. The interval is +1 to work well with the even and odds
totalSum += total;
aInt = bInt;
System.out.println(total);
}
System.out.println("");
System.out.println("Result: "+ (totalSum*deltaX)); //multiplication with deltaX is now here
为了考虑 f(x) 的正确因子,我将 prod2 更改为:
static double prod2(double a, double b, int interval, double n) {
int multiplier = 1;
if (interval > 0 && interval <= n){
//applying the right multiplier to f(x) given the current interval
multiplier = (interval % 2 == 0) ? 4 : 2;
}
return multiplier * Math.log(a);
}
现在它产生了正确的结果:
我应该计算
使用 Simpson 规则,有 4 个子区间。
我当然不想手工完成,所以我尝试在 Java 中编写该算法。
辛普森法则的公式是
这是我的代码:
import java.util.Scanner;
import java.util.Locale;
public class Simpson {
public static void main(String[] args) {
Scanner input = new Scanner(System.in).useLocale(Locale.US);
//e= 2.718281828459045 to copy paste
System.out.println("Interval a: ");
double aInt = input.nextDouble();
System.out.println("Interval b: ");
double bInt = input.nextDouble();
System.out.println("How many sub intervals: ");
double teilInt = input.nextDouble();
double intervaldistance = (bInt-aInt)/teilInt;
System.out.println("h = "+"("+bInt+"-"+aInt+") / "+teilInt+ " = "+intervaldistance);
double total = 0;
System.out.println("");
double totalSum=0;
for(double i=0; i<teilInt; i++) {
bInt = aInt+intervaldistance;
printInterval(aInt, bInt);
total = prod1(aInt, bInt);
total = total*prod2(aInt, bInt);
aInt = bInt;
System.out.println(total);
totalSum=totalSum+total;
total=0;
}
System.out.println("");
System.out.println("Result: "+totalSum);
}
static double prod1(double a, double b) { // first product of simpson rule; (b-a) / 6
double res1 = (b-a)/6;
return res1;
}
static double prod2(double a, double b) { // second pproduct of simpson rule
double res2 = Math.log(a)+4*Math.log((a+b)/2)+Math.log(b);
return res2;
}
static void printInterval(double a, double b) {
System.out.println("");
System.out.println("["+a+"; "+b+"]");
}
}
Output for 4 sub intervals:
[1.0; 1.4295704571147612]
0.08130646125926948
[1.4295704571147612; 1.8591409142295223]
0.21241421690076787
[1.8591409142295223; 2.2887113713442835]
0.31257532785558795
[2.2887113713442835; 2.7182818284590446]
0.39368288949073565
Result: 0.9999788955063609
现在,如果我将我的解决方案与其他在线计算器 (http://www.emathhelp.net/calculators/calculus-2/simpsons-rule-calculator/?f=ln+%28x%29&a=1&b=e&n=4&steps=on) 进行比较,它会有所不同。但我不明白为什么我的应该是错误的。
我的方案是0.9999788955063609
,网上的方案是0.999707944567103
可能是我弄错了?但是我已经仔细检查了所有内容,但找不到。
您可能通过多次执行 b_n = a_{n} + interval 来累积舍入误差。 相反,您可以使用归纳法,其中您说 a_n = a_0 + n*interval,因为这只涉及引入一次舍入误差。
我会用实际数字进行测试,以确认并稍微充实答案,但同时您可以观看handmade hero
关于误差累积的解释PS。作为奖励,您可以观看手工英雄的节选!
更新:我看过你的link。虽然我上面描述的问题 确实 适用,但精度差异很小(您将得到答案 0.9999788955063612)。您的情况出现差异的原因是在线计算器中使用的公式在符号方面略有不同,它将区间 [a,b] 视为 2h。也就是说,你的4个区间相当于他们计算的8个区间。
如果您在该网页中放置 8 个矩形,您将获得与此处(更准确)数字相同的结果:
Answer: 0.999978895506362.
查看该网页上使用的符号的更好解释 here
我将您的增量计算更改为顶部,这样您就不会一遍又一遍地计算增量。您也没有为奇数和偶数因素应用正确的乘数,也没有为 deltaX 应用正确的公式,因为它必须是:((a-b)/n) /3
double deltaX = ((bInt-aInt)/teilInt)/3;
for(int i=0; i<=teilInt; i++) { //changed to <= to include the last interval
bInt = aInt+intervaldistance;
printInterval(aInt, bInt);
total = prod2(aInt, bInt, i+1, teilInt); //added the current interval and n. The interval is +1 to work well with the even and odds
totalSum += total;
aInt = bInt;
System.out.println(total);
}
System.out.println("");
System.out.println("Result: "+ (totalSum*deltaX)); //multiplication with deltaX is now here
为了考虑 f(x) 的正确因子,我将 prod2 更改为:
static double prod2(double a, double b, int interval, double n) {
int multiplier = 1;
if (interval > 0 && interval <= n){
//applying the right multiplier to f(x) given the current interval
multiplier = (interval % 2 == 0) ? 4 : 2;
}
return multiplier * Math.log(a);
}
现在它产生了正确的结果: