Math.imul()
Функція Math.imul()
повертає результат C-подібного 32-бітного множення двох аргументів.
Спробуйте його в дії
Синтаксис
Math.imul(a, b)
Параметри
a
Перше число.
b
Друге число.
Повернене значення
Результат C-подібного 32-бітного множення переданих двох аргументів.
Опис
Math.imul()
дає змогу множити 32-бітні цілі числа з традиційною для C семантикою. Цей функціонал корисний для таких проєктів, як Emscripten.
Оскільки imul()
— це статичний метод об'єкта Math
, його потрібно завжди використовувати через Math.imul()
. Не слід звертатись до нього як до методу власноруч створеного екземпляра Math
(Math
не є конструктором).
Якщо використати звичайні для JavaScript числа з рухомою комою в imul
, ви помітите суттєву деградацію продуктивності коду. Це відбувається у зв'язку з дорогим перетворенням чисел з рухомою комою на цілі числа для множення, і наступною конвертацією цілочисельного результату множення назад у число з рухомою комою. Причина існування imul
полягає в тому, що ця функція швидша в одному (поки що) разі, а саме — AsmJS. AsmJS дозволяє JIT-оптимізаторам простіше реалізовувати цілі числа всередині JavaScript. Множення двох чисел, внутрішньо збережених як цілі числа (що можливо лише з AsmJS) через imul
— це єдина ситуація, де Math.imul
може бути ефективним в сучасних браузерах.
Приклади
Застосування Math.imul()
Math.imul(2, 4); // 8
Math.imul(-1, 8); // -8
Math.imul(-2, -2); // 4
Math.imul(0xffffffff, 5); // -5
Math.imul(0xfffffffe, 5); // -10
Поліфіл
Цей функціонал можна відтворити за допомогою наступної функції:
if (!Math.imul) Math.imul = function(a, b) {
var aHi = (a >>> 16) & 0xffff;
var aLo = a & 0xffff;
var bHi = (b >>> 16) & 0xffff;
var bLo = b & 0xffff;
// зміщення на 0 фіксує знак у старшій частині
// кінцеве |0 перетворює беззнакове значення на число зі знаком
return ((aLo * bLo) + (((aHi * bLo + aLo * bHi) << 16) >>> 0) | 0);
};
Однак, наступна функція — більш продуктивна, оскільки є ймовірність, що ті браузери, всередині яких цей поліфіл може використовуватись, не застосовують цілочисельний тип для оптимізації в JavaScript, натомість використовуючи числа з рухомою комою для всіх значень.
if (!Math.imul) Math.imul = function(opA, opB) {
opB |= 0; // впевнімося, що opB — ціле число. opA буде приведено автоматично.
// Числа з рухомою комою дають нам 53 бітів точності, в межах яким ми можемо працювати,
// плюс 1 знаковий біт, який, зручно для користувача, обробляється автоматично:
// 1. 0x003fffff /*opA & 0x000fffff*/ * 0x7fffffff /*opB*/ = 0x1fffff7fc00001
// 0x1fffff7fc00001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/
var result = (opA & 0x003fffff) * opB;
// 2. Ми можемо прибрати зведення до цілого з наведеної вище інструкції, оскільки:
// 0x1fffff7fc00001 + 0xffc00000 = 0x1fffffff800001
// 0x1fffffff800001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/
if (opA & 0xffc00000 /*!== 0*/) result += (opA & 0xffc00000) * opB |0;
return result |0;
};
Специфікації
Сумісність із браузерами
desktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
imul
|
Chrome Full support 28 | Edge Full support 12 | Firefox Full support 20 | Internet Explorer No support No | Opera Full support 16 | Safari Full support 7 | WebView Android Full support 4.4 | Chrome Android Full support 28 | Firefox for Android Full support 20 | Opera Android Full support 15 | Safari on iOS Full support 7 | Samsung Internet Full support 1.5 | Deno Full support 1.0 | Node.js Full support 0.12.0 |
Дивіться також
- Поліфіл для
Math.imul
доступний уcore-js
- Emscripten