Javascript中的快速双曲正切近似

时间:2011-05-24 23:28:35

标签: javascript performance math approximation

我在javascript中进行了一些数字信号处理计算,我发现计算双曲正切( tanh )有点太贵了。这就是我目前近似 tanh 的方式:

function tanh (arg) {
    // sinh(number)/cosh(number)
    return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
}

任何人都知道更快的计算方法吗?

8 个答案:

答案 0 :(得分:12)

来自here

function rational_tanh(x)
{
    if( x < -3 )
        return -1;
    else if( x > 3 )
        return 1;
    else
        return x * ( 27 + x * x ) / ( 27 + 9 * x * x );
}
  

这是一个理性的功能   近似一个tanh般柔软的剪刀。   它基于pade近似   tanh函数的调整   系数。

     

该函数在x = -3..3范围内   并输出范围y = -1..1。外   此范围必须钳制输出   到-1..1。

     

第一个衍生品   功能在-3和3消失,所以   过渡到硬裁剪区域   是C2连续的。

Padé逼近的幅度优于泰勒展开。夹紧也可能是一个问题(取决于你的范围)。

答案 1 :(得分:5)

您可以执行此操作并cut your performance time in half

function tanh(arg) {
    var pos = Math.exp(arg);
    var neg = Math.exp(-arg);
    return (pos - neg) / (pos + neg);
}

答案 2 :(得分:4)

不确定性能提升有多大,但

(exp(x) - exp(-x))/(exp(x) + exp(-x)) = (exp(2x) - 1)/(exp(2x) + 1)

你会将exp的数量减少一半。

答案 3 :(得分:1)

您可以始终以一定数量的准确度关闭公式。

function tanh (x) {
    return arg - (x * x * x / 3) + (2 * x * x * x * x * x / 15);
}

答案 4 :(得分:1)

这是我对这个问题的回答

function tanh(x){
     var e = Math.exp(2*x)
     return (e-1)/(e+1)
}

Math.constructor.prototype.tanh=tanh;
document.write(Math.tanh(2))

答案 5 :(得分:1)

要使用较少的Math.exp() s获得准确的答案,您可以使用tanh和logistic function之间的关系。 Tanh(x)正好是2 * logistic(2 * x) - 1,并且扩展了后勤功能,您得到:

  function one_exp_tanh(x){
      return 2.0 / (1.0 + exp(-2.0 * x)) - 1.0;
  }

我不知道这在javascript中是否更快。

答案 6 :(得分:0)

在chrome上调用该函数所需的时间不到调用空function f(){}的三倍所以我认为你不会在重写时获得太多收益。

问题是函数开销,而不是公式。可能是内联它可以保存更有趣的东西......

修改

要进行测试,我只需在Chrome中打开一个控制台(ctrl-shift-C)并使用

创建一个计时功能
timeit = function(f) {
     var start=(new Date).getTime();
     for (var i=0; i<100000; i++)
         f(1);
     return (new Date).getTime() - start;
}

然后使用function(){}和您的函数进行测试。

然而事实证明,这种测试非常不可靠。我甚至得到了荒谬的结果,timeit(f1)报告200和timeit(f2)报告120(相当不同),但f1f2确实是两个链接到同一个功能对象的变量。此外,timeit(f)timeit(function(x){ return Math.cos(x); })之间存在差异,即使f恰好是该功能。

可能有一个解释因为V8和javascript控制台如何互动,但我不知道它是什么。

同样使用FF4,这种方法会产生非常不可靠的结果......

答案 7 :(得分:0)

ES6原生提供此方法和许多其他触发函数:

  • Math.sinh - 数字的双曲正弦
  • Math.cosh - 数字的双曲余弦
  • Math.tanh - 数字的双曲正切
  • Math.asinh - 数字的双曲弧正弦
  • Math.acosh - 数字的双曲弧余弦
  • Math.atanh - 数字的双曲反正切
  • Math.hypot - 平方和的平方根

最有可能它比大多数JS替代品更快。