Если я хочу найти самый быстрый способ вычисления x * 2, какой из них мне следует использовать?
x << 1
или
x * 2
При таком же логическом мышлении, если я хочу найти самый быстрый способ вычисления x/2, какой из них мне следует использовать?
x >> 1
или
x / 2
Почему?
@RoryMcCrossan Не могли бы вы рассказать, почему они быстрее? Затем вы можете сразу преобразовать его в ответ.
Тут не так много, как я думал, разница в преимуществе побитовых операторов примерно 2% jsperf.app/tegeto. Еще больше причин не беспокоиться о них в JS (если только вы на самом деле не работаете с битовыми значениями).
конечно, ограничено 32-битными целыми числами
умножение/деление и сдвиг влево/вправо — это не одна и та же операция. Они близки по многим параметрам, но все же не являются одним и тем же. Рассмотрим 3 / 2 === 1.5
и 3 >> 1 === 1
. Итак, сдвиг больше похож на целочисленное деление. Опять же, это не совсем то же самое, что деление (даже если не учитывать деление нечетных чисел): 40000000000 /2 === 20000000000
и 40000000000 >> 1 === 672647168
, поскольку побитовые операторы работают только с 32-битными числами.
В любом случае, реальный ресурс, с которого вам нужно начать, это: Что быстрее?
мои браузеры выполняют от 1 (на основе Chrome) до 2 (Mozilla) МИЛЛИАРДОВ операций (*
и <<
) в секунду - с разницей менее 0,1% (в пределах погрешности для таких измерений)... так что... делайте то, что хотите хочу - если вы не делаете миллиарды таких вычислений, это действительно не имеет значения ни на йоту
на уровне процессора [->регистр] операция сдвига занимает всего несколько тактов, а умножение проходит через сложную арифметическую оптимизацию, которая обязательно требует больше циклов и циклов, даже в случае простого умножения/деления на 2 [или кратное 2]. Этот вид оптимизации полезен только в случаях абсолютной необходимости производительности, как в случае с заказом на ракету; есть также случай первого запуска Ariane 5, разрушенного из-за переполнения 32-битного регистра.
Это совершенно разные операции: сдвиг битов (и, по сути, все побитовые операции) приводит к тому, что результат становится 32-битным целым числом. Умножать и делить не надо. Фактически: битовые операции можно (правильно) использовать только с целыми числами для выполнения 32-битных математических вычислений. Обычные арифметические операции можно использовать со всеми числами, которые представляют собой 64-битные числа с плавающей запятой и безопасными целыми числами длиной до 53 бит. Таким образом, с точки зрения производительности, если вам нужно умножить на два, битовый сдвиг 0b11111111111111111111111111111111 << 1
будет эффективен 0% в 100% случаев, потому что он не умножается на 2.
Нет никакой разницы:
` Chrome/127
---------------------------------------------------
shift ■ 1.00x | x1000000000 246 246 252 255 262
multiply ■ 1.00x | x1000000000 246 252 254 257 258
--------------------------------------------------- `
Открыта детская площадка
// @benchmark shift
2 << 1
// @benchmark multiply
2 * 2
/*@skip*/ fetch('https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js').then(r => r.text().then(eval));
Да, результаты схожи, но я подозреваю здесь действие оптимизатора кода, и это хорошо.
Да, они быстрее, но за это приходится жертвовать удобочитаемостью и простотой понимания. Разница в производительности обычно настолько мала и бессмысленна для JS, что использование стандартных математических операторов является подходом по умолчанию.