java - 如何将泰勒级数写为函数

标签 java

我必须编写一个泰勒级数,直到第 16 个元素来计算 sin 并将返回值与 Math.sin 进行比较。好吧,一切都工作正常,直到最后一次我得到 0.006941 而不是 0.00000。我的错误在哪里,如果有人知道如何以更专业的方式编写它,我会非常高兴。

import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        NumberFormat formatter = new DecimalFormat("#0.000000");
        double val[] = {0, Math.PI / 3, Math.PI / 4, Math.PI / 6, Math.PI / 2, Math.PI};

        for (int i = 0; i < val.length; i++) {

            System.out.println("With Taylor method: " + formatter.format(Taylor(val[i])));
            System.out.println("With Math.sin method: " + formatter.format(Math.sin(val[i])));


        }
    }

        public static double Taylor ( double val){
            ArrayList<Double> memory = new ArrayList<Double>();
            double row = val;
            for (int i = 0, s = 3; i < 16; i++, s = s + 2) {

                double mth = Math.pow(val, s);
                double result = mth / factorial(s);
                memory.add(result);

            }

            for (int i = 0; i < 16; i++) {
                if (i % 2 == 0) {
                    double d = memory.get(i);

                    row = row - d;

                } else {
                    double d = memory.get(i);

                    row = row + d;

                }
            }
            return row;

        }

        public static long factorial ( double n){
            long fact = 1;
            for (int i = 2; i <= n; i++) {
                fact = fact * i;
            }
            return fact;
        }


    }

最佳答案

你的数学是正确的,但是一旦你开始计算 21!,你的阶乘就溢出了。我打印出了计算出的阶乘。

factorial(3) = 6
factorial(5) = 120
factorial(7) = 5040
factorial(9) = 362880
factorial(11) = 39916800
factorial(13) = 6227020800
factorial(15) = 1307674368000
factorial(17) = 355687428096000
factorial(19) = 121645100408832000
factorial(21) = -4249290049419214848  // Overflow starting here!
factorial(23) = 8128291617894825984
factorial(25) = 7034535277573963776
factorial(27) = -5483646897237262336
factorial(29) = -7055958792655077376
factorial(31) = 4999213071378415616
factorial(33) = 3400198294675128320

看来您的筹款val直到达到数组中的最高值 Math.PI 为止,直到更高的幂都不足以对溢出产生影响。本身。由于溢出而导致的错误非常严重。

相反,使用最后一项作为起点来计算每一项。如果您有输入 memory 的最后一个值,然后乘以 val * val乘以该值,然后按顺序除以接下来的两个数字以获得阶乘部分。

那是因为memory.get(i)等于memory.get(i - 1) * (val * val) / ((s - 1) * s) 。这也使您的计算更加高效。它避免了计算分子(幂部分)和分母(阶乘计算)时的乘法重复。这也将避免因单独计算分母而导致的溢出。

我对这个想法的实现用它代替了第一个 for 循环:

double mth = val;

for (int i = 0, s = 3; i < 16; i++, s = s + 2) {
    mth = mth * val * val;
    mth = mth / ((s - 1) * s);
    memory.add(mth);
}

和地点

double row = val;

for之间循环,以确保第一项是之前的初始总和。那么你甚至不需要 factorial方法。

这个我得到0.000000对于 Math.PI .

关于java - 如何将泰勒级数写为函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57484538/

相关文章:

java - 有人可以用 Java 解释几行关于链表的内容吗?

java - spring mvc中如何根据环境 Autowiring 不同的服务?

java - 如何使用 css 更改 Javafx 中 slider 轨道的颜色?

java - Kotlin 单元测试变量声明 Lateinit、Lazy、可为 null 与不可为 Null

java - 使用 simpleDateFormat java 解析日期

java - 使用 JPQL JOIN ON 标准

java - 通过传递泛型方法进行重构

java - 如何使用上下文包装器在运行时更改应用程序语言?

java - Java中如何按两个字段排序并指定排序方向?

java - TcpInboundGateway - 读取特定数量的字节