Быстрый и безопасный способ убрать знак подписанного числа в 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(). Возвращает абсолютное значение числа

Поскольку лучшего ответа не появилось, я сам подведу итоги этого ответа.

  1. if(n < 0) n *= -1 На данный момент лучший выбор. Он работает достаточно хорошо на большинстве платформ и очень удобочитаем. Это также сохраняет десятичные дроби.
  2. Другие варианты, такие как n = Math.abs(n), может быть быстрее на других платформах. Но выигрыш обычно составляет всего несколько процентов. Вы можете подумать об обнаружении браузера / платформы заранее и создании зависимого от платформы кода, который использует тот или иной вариант. Это может дать вам лучшую производительность на каждой платформе, но приводит к большим накладным расходам.
  3. Будьте внимательны при рассмотрении побитовых операторов, они могут быть быстрее на некоторых платформах, но могут изменить семантику вашей программы (удаляя десятичные дроби).

Побитовые операторы самые быстрые, смотрите результаты.

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), которые также неизменно быстрые.

jsPerf: https://jsperf.com/remove-sign-from-a-number

Вы также можете использовать n=Math.sqrt(n^n)

Другие вопросы по тегам