Java 如何编写泰勒级数作为函数

Java 如何编写泰勒级数作为函数,java,Java,我必须编写一个泰勒级数,直到第16个元素计算sin,并将返回的值与Math.sin进行比较。好吧,直到最后一次我得到的不是0.00000,而是0.006941,一切都正常。我的错误在哪里?如果有人知道如何以更专业的方式写这篇文章,我会非常高兴 import java.text.NumberFormat; import java.text.DecimalFormat; import java.util.ArrayList; public class Main { public stat

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

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;
        }


    }
导入java.text.NumberFormat;
导入java.text.DecimalFormat;
导入java.util.ArrayList;
公共班机{
公共静态void main(字符串[]args){
NumberFormat格式化程序=新的十进制格式(“0.000000”);
double val[]={0,Math.PI/3,Math.PI/4,Math.PI/6,Math.PI/2,Math.PI};
对于(int i=0;i对于(int i=2;i你的数学是正确的,但是一旦你开始计算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
本身,才足以对溢出产生影响。溢出导致的错误非常严重

相反,用最后一个项作为起点来计算每个项。如果您有最后一个输入到
内存中的值
,则只需将
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);
}
for
循环之间,确保第一项是与之前相同的初始和。这样,您甚至不需要
阶乘方法


我不知道这是否是问题的原因,但我希望使用
Math.pow
factorial
来计算正弦泰勒级数中的每一项比从上一项计算每一项的精度要低很多通过
-x^2/n(n-1)
进行最终验证。太棒了!非常感谢!
double row = val;