【问题标题】:Is my Simpson's rule calculator correct (java)?我的辛普森规则计算器是否正确(java)?
【发布时间】:2017-12-04 22:54:40
【问题描述】:

我应该计算一下

使用辛普森规则,有 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

也许我犯了一个错误?但是我仔细检查了所有内容,但找不到。

【问题讨论】:

  • 没有仔细阅读代码,但是您将整数 (6,4,2) 与 doubles 混合在一起,这可能会导致舍入错误。尝试将它们定义为doubles,而不是(6.0,4.0,2.0),看看是否有效果。
  • 您列出的链接有 n=4。当我将 url 更改为 n=16 而不是 n=4 时,我得到了答案:0.999998619003165。
  • @MickMnemonic 当我读到你的评论时,我有一种很好的感觉,但遗憾的是它没有帮助:( 无论如何,这真的很好知道,当我编写更多这样的代码时我会意识到这一点。
  • @RyanStout 该任务针对 16 个子间隔。但是在这个问题中,我花了 4 个间隔才没有让这个问题变得更长。
  • 您的问题是您运行了 16 个间隔,并且您提供了一个使用 4 个间隔的链接。也许更新问题?

标签: java algorithm math calculator precision


【解决方案1】:

您可能会通过多次执行 b_n = a_{n} + interval 来累积舍入误差。 相反,您可以使用归纳方法,即 a_n = a_0 + n*interval,因为这只涉及引入一次舍入误差。

我将用实际数字进行测试以确认和充实答案,但同时您可以从handmade hero观看有关错误累积的解释


PS。作为奖励,您可以观看手工英雄的节选!

更新:我看了你的链接。虽然我上面描述的问题确实适用,但精度差异很小(你会得到答案 0.9999788955063612 代替)。您的情况存在差异的原因是您的在线计算器中使用的公式在符号方面略有不同,它将区间 [a,b] 视为 2h。换句话说,您的 4 个区间在他们的计算中相当于 8 个区间。

如果您在该网页中放置 8 个矩形,您将得到与此处(更准确)数字相同的结果:

答案:0.999978895506362。

查看该网页上使用的符号的更好解释here

【讨论】:

    【解决方案2】:

    我将您的增量计算更改为顶部,这样您就不会一遍又一遍地计算增量。您也没有为奇数和偶数因子应用正确的乘数,也没有为 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);        
    }
    

    现在它产生了正确的结果:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-19
      • 2016-05-05
      • 1970-01-01
      • 2015-12-15
      • 2020-01-19
      • 2014-01-06
      • 2016-08-16
      • 2014-12-17
      相关资源
      最近更新 更多