Быстрое касательное приближение гиперболического в Javascript - PullRequest
9 голосов
/ 25 мая 2011

Я делаю некоторые вычисления цифровой обработки сигналов в javascript и обнаружил, что вычисление гиперболического тангенса ( tanh ) слишком дорого.Вот как я сейчас приблизительно tanh :

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

Кто-нибудь знает более быстрый способ его расчета?

Ответы [ 8 ]

12 голосов
/ 25 мая 2011

С здесь .

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.Он основан на аппроксимации паде функции tanh с подправленными коэффициентами.

Функция находится в диапазоне x = -3..3 и выводит диапазон y = -1..1.За пределами этого диапазона выходной сигнал должен быть ограничен до -1..1.

Первые производные функции обращаются в ноль при -3 и 3, поэтому переход в область жесткого ограничения является непрерывным C2.

Приближение Паде на величины лучше, чем разложение Тейлора.Зажим также может быть проблемой (в зависимости от вашего диапазона).

5 голосов
/ 25 мая 2011

Вы можете сделать это и сократить время исполнения наполовину :

function tanh(arg) {
    var pos = Math.exp(arg);
    var neg = Math.exp(-arg);
    return (pos - neg) / (pos + neg);
}
4 голосов
/ 25 мая 2011

Не уверен, насколько велико будет увеличение производительности, но

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

Вы сократите число exp с пополам.

1 голос
/ 18 июля 2013

Для точного ответа, используя меньше Math.exp() с, вы можете использовать соотношение между tanh и логистической функцией . Tanh(x) - это точно 2 * logistic(2 * x) - 1, и, расширив логистическую функцию, вы получите:

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

Я не знаю, быстрее ли это в JavaScript,

1 голос
/ 05 января 2012

это мой ответ на эту проблему

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

Math.constructor.prototype.tanh=tanh;
document.write(Math.tanh(2))
1 голос
/ 25 мая 2011

Вы всегда можете обрезать формулу с определенным уровнем точности.

function tanh (x) {
    return arg - (x * x * x / 3) + (2 * x * x * x * x * x / 15);
}
0 голосов
/ 08 ноября 2015

ES6 предоставляет этот метод и многие другие функции триггера изначально:

  • Math.sinh - гиперболический синус числа
  • Math.cosh - гиперболический косинус числа
  • Math.tanh - гиперболический тангенс числа
  • Math.asinh - гиперболический арксинус числа
  • Math.acosh - гиперболический арккосинус числа
  • Math.atanh - гиперболический арктангенс числа
  • Math.hypot - квадратный корень из суммы квадратов

Скорее всего, это будет быстрее, чем большинство альтернатив JS.

0 голосов
/ 25 мая 2011

Для вызова этой функции в Chrome требуется менее чем в три раза больше, чем для вызова пустой function f(){}, поэтому я думаю, что вы не получите много пользы от переписывания.

Проблема в служебной нагрузке, а не в формуле. Может быть, это может помочь сохранить что-то более интересное ...

EDIT

Чтобы протестировать, я просто открыл консоль в 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 (большая разница), но f1 и f2 действительно были двумя переменными, связанными с одним и тем же функциональным объектом. Также была разница между timeit(f) и timeit(function(x){ return Math.cos(x); }), даже когда f была именно этой функцией.

Может быть, есть объяснение тому, как взаимодействуют V8 и консоль javascript, но я не знаю, что это такое.

Также с FF4 этот подход дает очень ненадежные результаты ...

...