Math.imul() выполняет 32-битное целочисленное умножение.
Проще всего запомнить так: это не обычное умножение чисел JavaScript, а умножение так, как если бы оба значения были 32-битными целыми числами.
Именно поэтому Math.imul() иногда даёт результат, который отличается от обычного *.
Синтаксис
Math.imul(a, b)
a- первое значениеb- второе значение
Оба аргумента сначала приводятся к 32-битным целым числам, а потом перемножаются.
Что делает Math.imul()
Метод умножает два значения как 32-битные целые числа.
console.log(Math.imul(2, 4)); // 8
console.log(Math.imul(-1, 8)); // -8
console.log(Math.imul(-1, -1)); // 1
Это значит:
Math.imul(2, 4)даёт8Math.imul(-1, 8)даёт-8Math.imul(-1, -1)даёт1
На небольших значениях результат часто совпадает с обычным *.
Что возвращает Math.imul()
Math.imul() возвращает значение типа number.
const result = Math.imul(6, 7);
console.log(result); // 42
console.log(typeof result); // "number"
Но важно понимать: по смыслу это число интерпретируется как результат 32-битного целочисленного умножения.
Чем Math.imul() отличается от обычного *
Это главный смысл метода.
Обычный оператор * работает с обычными числами JavaScript.
Math.imul() работает с 32-битными целыми числами и учитывает переполнение.
Пример:
console.log(0xffffffff * 5); // 21474836475
console.log(Math.imul(0xffffffff, 5)); // -5
Ещё пример:
console.log(0x7fffffff * 2); // 4294967294
console.log(Math.imul(0x7fffffff, 2)); // -2
То есть:
*считает обычное числоMath.imul()считает результат в рамках 32-битного целого диапазона
Почему появляются странные отрицательные результаты
Это связано с переполнением 32-битного целого числа.
Например:
console.log(Math.imul(0x7fffffff, 2)); // -2
Хотя математически результат должен быть 4294967294, в 32-битном знаковом формате это значение интерпретируется как -2.
Это не ошибка метода. Это его нормальное поведение.
На обычных числах всё выглядит привычно
Если значения небольшие, результат обычно совпадает с обычным умножением.
console.log(123456 * 789); // 97406784
console.log(Math.imul(123456, 789)); // 97406784
Поэтому разница заметна не всегда, а в основном там, где важна именно 32-битная арифметика.
Аргументы сначала приводятся к 32-битным целым числам
Это самый важный нюанс при работе с Math.imul().
Метод не умножает аргументы как есть. Сначала оба значения приводятся к 32-битным целым числам.
Из-за этого некоторые результаты могут удивлять.
Дробные числа
Дробные значения сначала отбрасывают дробную часть.
console.log(Math.imul(1.9, 4)); // 4
console.log(Math.imul(0.5, 8)); // 0
Здесь важно понимать:
1.9превращается в10.5превращается в0
И уже после этого выполняется умножение.
Большие числа
Очень большие значения тоже могут вести себя неожиданно, потому что метод работает только с 32 битами.
console.log(Math.imul(4294967296, 2)); // 0
Здесь число выходит за пределы 32-битного диапазона и после преобразования становится 0, поэтому итог тоже 0.
Отрицательные значения
С отрицательными числами метод работает нормально, но всё равно в рамках 32-битной арифметики.
console.log(Math.imul(-1, 8)); // -8
console.log(Math.imul(-1, -8)); // 8
console.log(Math.imul(-1, -1)); // 1
Что происходит с 0
Если один из аргументов после преобразования становится 0, результат тоже будет 0.
console.log(Math.imul(0, 5)); // 0
console.log(Math.imul(-0, 5)); // 0
console.log(Math.imul(0.5, 8)); // 0
Это полезно помнить: Math.imul() не сохраняет -0 как отдельный результат.
Без аргументов
Если вызвать Math.imul() без аргументов, результатом будет 0.
console.log(Math.imul()); // 0
Если передать только один аргумент, результат тоже будет 0.
console.log(Math.imul(5)); // 0
Это может показаться неожиданным, особенно если вы привыкли, что многие методы Math без аргументов дают NaN.
Неявное приведение типов
Math.imul() сначала пытается привести аргументы к числам, а затем к 32-битным целым.
console.log(Math.imul("5", "6")); // 30
console.log(Math.imul(null, 4)); // 0
console.log(Math.imul(true, 4)); // 4
console.log(Math.imul(undefined, 4)); // 0
На практике лучше передавать в метод уже готовые числа.
Массивы и странные значения
Из-за приведения типов некоторые значения могут вести себя неочевидно.
console.log(Math.imul([], 4)); // 0
console.log(Math.imul([5], 4)); // 20
console.log(Math.imul([1, 2], 4)); // 0
Это ещё одна причина, почему лучше не полагаться на неявное преобразование.
NaN и Infinity
Для специальных значений результат будет таким:
console.log(Math.imul(NaN, 4)); // 0
console.log(Math.imul(Infinity, 4)); // 0
console.log(Math.imul(-Infinity, 4)); // 0
Это важно помнить:
NaNдаёт0Infinityдаёт0-Infinityдаёт0
Причина в том, что после преобразования эти значения становятся 0 в 32-битном формате.
Math.imul() и побитовые операции
Math.imul() особенно полезен рядом с побитовыми операциями и низкоуровневой логикой.
Например, в хеш-функциях или алгоритмах, где важно точно повторять 32-битную арифметику.
Это как раз тот случай, где обычный * может быть не тем, что нужно.
Числа не меняются
Math.imul() не изменяет исходные значения. Он только возвращает новый результат.
const a = 6;
const b = 7;
const result = Math.imul(a, b);
console.log(a); // 6
console.log(b); // 7
console.log(result); // 42
Когда это полезно
Math.imul() удобно использовать, когда:
- нужна именно 32-битная целочисленная арифметика
- вы работаете с побитовыми операциями
- пишете хеши, генераторы или низкоуровневые алгоритмы
- важно предсказуемое переполнение как у 32-битных целых чисел
Пример:
const value = Math.imul(0xffffffff, 5);
console.log(value); // -5
Для обычной бизнес-логики чаще хватает *, но для низкоуровневых вычислений Math.imul() бывает очень полезен.
Частые ошибки
Думать, что это обычное умножение
console.log(0xffffffff * 5); // 21474836475
console.log(Math.imul(0xffffffff, 5)); // -5
Math.imul() - это не замена *, а отдельный инструмент для 32-битной арифметики.
Забывать про преобразование к целому числу
console.log(Math.imul(1.9, 4)); // 4
Дробная часть здесь не участвует в вычислении.
Ожидать NaN для undefined или Infinity
console.log(Math.imul(undefined, 4)); // 0
console.log(Math.imul(Infinity, 4)); // 0
Из-за 32-битного преобразования здесь получится 0, а не NaN.
Быстрая памятка
Math.imul(a, b)делает 32-битное целочисленное умножение- метод возвращает
number - результат может отличаться от обычного
* - перед умножением аргументы приводятся к 32-битным целым
- дробные части отбрасываются
- большие числа могут переполняться
Math.imul()особенно полезен для побитовой и низкоуровневой логикиNaN,Infinityиundefinedпосле преобразования часто дают0
Коротко
Math.imul() - это стандартный способ выполнить 32-битное целочисленное умножение в JavaScript. Главное, что нужно запомнить: метод работает не как обычный *, а как умножение в рамках 32-битной арифметики, поэтому может давать переполнение, отбрасывать дробную часть и возвращать результаты, которые на первый взгляд кажутся неожиданными.