【问题标题】:Javascript sin/cosin taylor expansionJavascript 正弦/余弦泰勒展开
【发布时间】:2016-09-09 18:50:06
【问题描述】:

我写的函数有问题。想法是使用 taylor 扩展而不是 js 数学对象来计算 sin 和 cosin 值(在 radians 上操作)。这些是方程式:

sin(x) = (x^1)/1! - (x^3)/3! + (x^5)/5! - (x^7)/7! + (x^9)/9! - (x^11)/11! + ...

cos(x) = (x^0)/0! - (x^2)/2! + (x^4)/4! - (x^6)/6! + (x^8)/8! - (x^10)/10! + ...

我知道当我输入类似myCos(10,2) 的内容时,由于迭代次数少,结果会不准确,但是我不明白为什么(例如)x = 10 结果在特别是@987654331 开始变得真实@,并在 iterNum = 80 处变为 NaN。关键是对于myCos/Sin(1-40, 5-50)(或多或少)这样的范围,函数有效,但对于更大的数字,结果变为 NaN。不确定我的解释是否可以理解,但我希望可以,继续在控制台中使用该功能,您会看到问题所在
这是我的代码:

function power(a,n) {
    var result = 1;
    for (var i = 0; i < n; i++) {
        result = result * a;
    }
    return result;
}
function factorial(z) {
    var result = 1;
    for (var i = 1; i <= z; i++) {
        result = result * i;
    }
    return result;
}
function mySin(x, iterNum) {
    var sin = 0;
    var n = 1;
    for (var i = 0; i <= iterNum; i++) {
        sin = sin + (power(x,n)/factorial(n) - power(x,n+2)/factorial(n+2));
        n = n + 4;
    }
    console.log(sin + " = my function.");
    console.log(Math.sin(x)  + " math.sin");
}
function myCos(x, iterNum) {
    var cos = 0;
    var n = 0;
    for (var i = 0; i <= iterNum; i++) {
        cos = cos + (power(x,n)/factorial(n) - power(x,n+2)/factorial(n+2));
        n = n + 4;
    }
    console.log(cos + " = my function.");
    console.log(Math.cos(x) + " math.cos");
}

【问题讨论】:

标签: javascript math


【解决方案1】:

你遇到的问题是

> Infinity/Infinity
NaN

因此,当 powerfactorial 生成的值大于 JavaScript 的浮点数可以表示的值时,您将 NaN 添加到您的总和中,并将其传播到结果中。

你应该可以通过使用来修复它

for (var i = 0; i <= iterNum; i++) {
    var member = power(x,n)/factorial(n) - power(x,n+2)/factorial(n+2);
    if (isNaN(member)) // maybe || member === 0
        break;
    sin += member;
    n += 4;
}

【讨论】:

  • 正确的理由和建设性的解决方案建议。此外,从整数开始然后突然得到实数的原因是由于整数数据类型的范围。您正在使用 JavaScript,它就像关于数据类型的变色龙。在某些时候,您的幂或阶乘函数结果之一变得太大而无法放入整数,因此它变成了浮点数。从现在开始,您将使用浮点数。
  • @ChrisTophski:您不需要将整数转换为浮点数以进行任何语言的除法吗?
  • 不一定,或者至少只是隐含的。在强类型语言中,您将定义一个接受浮点数的函数。然后你无论如何都在函数内部使用浮点数,并给出一个整数作为参数,它将被隐式转换为浮点数。此处针对特定问题的一种解决方案是将至少一个操作数与1.0 相乘,以确保给定整数被解释为浮点数。如果这是你的意思,我完全同意你的看法。
  • @ChrisTophski:您似乎暗示powerfactorial 将返回整数,然后需要对其进行转换(因为我们不想要整数除法)。如果它们已经返回浮点数,它的工作方式与 JavaScript 相同。
  • @mkrds 泰勒级数对于较大的值不太适用,它最终会发散。你需要一个非常大的iterNum,比你在 JavaScript 中仍然可以获得有用的幂和阶乘值更大。这就是为什么每个真正的实现都首先使用x = x % Math.PI
【解决方案2】:

正弦级数中 k-1 项和 k 之间的商具有很好的简单形式

-x*x / ( (2*k)*(2*k+1) )

这允许使用最少的浮点运算实现非常简单的实现:

function mySin(x, iterNum) {
    var mxx = -x*x;
    var sin = 1;
    var n = 0;
    var term = 1;
    for (var i = 1; i <= 2*iterNum; i++) {
        n = n + 2;
        term = term * mxx / ( n*(n+1) );
        sin = sin + term
    }
    sin = x*sin;
    console.log(sin + " = my function.");
    console.log(Math.sin(x)  + " math.sin");
}

由于实际上既没有计算幂也没有计算阶乘,因此该计算中的最大值是 n-0.5 exp(x) 的项。这仍然会导致值 NaN,但只能高于 x&gt;705

【讨论】:

    猜你喜欢
    • 2021-07-10
    • 2017-04-10
    • 2017-06-06
    • 2017-12-02
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    • 1970-01-01
    相关资源
    最近更新 更多