Что быстрее: Math.abs (значение) или значение * -1? - PullRequest
39 голосов
/ 14 января 2009

Довольно просто, но я просто хочу знать, что быстрее.

Я думаю, что простое умножение числа на -1 намного быстрее, чем вызов предопределенного метода, при условии, что вы уверены, что значение отрицательное.

Но если это так, то для чего нужна функция abs()? Это просто для того, чтобы убедиться, что возвращаемое значение всегда будет положительным независимо от знака значения?

Ответы [ 5 ]

70 голосов
/ 14 января 2009

Обновлено август 2012 г. :

Я провел профилирование с этими реализациями:

/* Test 1: */ b = Math.abs(a);
/* Test 2: */ b = abs(a); //local copy: abs = Math.abs;
/* Test 3: */ b = a < 0 ? a * -1 : a;
/* Test 4: */ b = a < 0 ? -a : a;

Я получил следующий результат в Windows 7. Значения нормализуются после самого быстрого результата для каждого браузера, чтобы упростить сравнение, какой метод быстрее:

        1:Math 2:abs 3:*-1  4:-    1.0=   Version
Chrome    1.0   1.0   1.0   1.0    111ms  21.0.1180.75 m
Firefox   1.0   1.0   1.2   1.2    127ms  14.0.1
IE        1.4   1.0   1.1   1.0    185ms  9.0.8112
Opera     1.9   1.6   1.1   1.0    246ms  12.00
Safari    1.6   1.6   1.1   1.0    308ms  5.1.7

Вывод: Когда я делал этот тест 3 года назад, -a был самым быстрым, но теперь Math.abs (x) быстрее в Firefox! В Chrome abs(a) и -a получили одно и то же время, и разница между самым медленным методом составляла всего 3 мс, когда я тестировал его с 10 000 000 чисел.

Моя рекомендация : Используйте Math.abs (a) . Если вы находитесь в тесном цикле и профилирование показало, что оно слишком медленное, вы можете использовать локальную ссылку на функцию abs:

var abs=Math.abs; //A local reference to the global Math.abs function
for (i=0;i<1234567890;++i) if ( abs( v[i] ) > 10) ++x;
24 голосов
/ 14 января 2009

Я бы предложил выбрать метод, который более четко показывает ваши намерения, а не беспокоиться о производительности. В этом случае выигрыш в производительности умножения на -1, вероятно, минимален.

Когда вы используете Math.abs(), очень ясно, что вы хотите положительное значение. Когда вы используете * -1, это не ясно, и требует дополнительного изучения, чтобы определить, всегда ли входное значение отрицательно.

11 голосов
/ 14 января 2009

Полагаю, это зависит от реализации, но Math.abs может быть таким простым:

function abs(x) {
    return x < 0 ? x * -1 : x;
}

Итак, теоретически, он просто добавляет быстрый тест перед умножением.

Но, да, отрицание отрицательного знака является единственной целью. Дело в том, что простой x * -1 также непродуктивен для положительных значений.


@ olliej [комментарии]

True. Простое редактирование. ;)

function abs(x) {
    return Number(x < 0 ? x * -1 : x);
}
4 голосов
/ 14 января 2009

Просто операция *-1, вероятно, быстрее, но имейте в виду, что конечный результат отличается от результата для math.abs ().

math.abs(-5) и math.abs(5) оба возвращают 5.

-5 * -1 также возвращает 5.

5 * -1 возвращает -5.

Так что, если вы не уверены, что число отрицательное для начала, вам нужно выполнить несколько тестов, которые стоят больше времени. Можете также сделать math.abs ().

Но на самом деле, если разница в производительности между abs () и * -1 имеет значение в вашем JS, у вас, вероятно, есть более серьезные проблемы.

2 голосов
/ 14 января 2009

Вопрос стиля: зачем использовать a * -1 вместо -a? Кроме того, я согласен, что вы должны использовать abs(), если вы не знаете знак номера заранее. Я не заботился бы о скорости, но о удобочитаемости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...