Быстрый и безопасный способ убрать знак подписанного числа в JavaScript
Я хочу удалить знак числа в JavaScript. Вот тестовые случаи, которые я уже исследовал в jsperf ( http://jsperf.com/remove-sign-from-number)
if(n < 0) n *= -1;
if(n < 0) n = -n;
n = Math.abs(n)
(n < 0) && (n *= -1)
(n < 0) && (n = -n)
n = Math.sqrt(n*n)
Согласно этим тестам: if(n < 0) n *= -1
кажется хорошим решением.
Знаете ли вы какой-нибудь лучший, экономичный и эффективный способ сделать это?
Редактировать 1: добавлено Nikhil's Math.sqrt
дело, но sqrt
обычно довольно медленно в большинстве систем.
Редактировать 2: Предложение Яна о побитовых операциях может быть быстрее в некоторых случаях, но также удалит дробные цифры и, следовательно, не будет работать для меня.
6 ответов
Вы можете использовать Math.abs(). Возвращает абсолютное значение числа
Поскольку лучшего ответа не появилось, я сам подведу итоги этого ответа.
if(n < 0) n *= -1
На данный момент лучший выбор. Он работает достаточно хорошо на большинстве платформ и очень удобочитаем. Это также сохраняет десятичные дроби.- Другие варианты, такие как
n = Math.abs(n)
, может быть быстрее на других платформах. Но выигрыш обычно составляет всего несколько процентов. Вы можете подумать об обнаружении браузера / платформы заранее и создании зависимого от платформы кода, который использует тот или иной вариант. Это может дать вам лучшую производительность на каждой платформе, но приводит к большим накладным расходам. - Будьте внимательны при рассмотрении побитовых операторов, они могут быть быстрее на некоторых платформах, но могут изменить семантику вашей программы (удаляя десятичные дроби).
Побитовые операторы самые быстрые, смотрите результаты.
if(n < 0) n = ~n+1;
Не уверен, что это проблема типа XY, но сдвиг вправо с заполнением нулями на 0 избавляет от знакового бита. Я не могу придумать более быстрого способа.
1 >>> 0; // 1
-1 >>> 0; // 4294967295
Вот еще один способ:
n * (n>>31|!!n)
(не обязательно самый быстрый во всех браузерах, просто по-другому)
Это всегда даст положительное число. В принципе >>
сдвигает все биты и держит знак. Это тогда побитовое ИЛИ с 0 или 1 (если положительное вместо), производя или -1, 0 или 1. Это означает, что знак умножается сам по себе, делая его всегда четным.
Или даже с помощью простых троичных операций:
n * (n < 0 ? -1 : 1)
или же
n = n < 0 ? -n : n
Второй кажется одинаково быстрым во всех браузерах, как и некоторые другие из оригинального jsPerf OP: n > 0 || (n *= -1)
а также n < 0 && (n = -n)
, которые также неизменно быстрые.