Signatur
Beschreibung
Math.imul() wandelt beide Argumente zuerst in 32-Bit-Ganzzahlen um und multipliziert sie dann. Das Ergebnis wird auf die unteren 32 Bit gekürzt und als vorzeichenbehaftete 32-Bit-Ganzzahl (Bereich −231 bis 231−1) zurückgegeben. So verhält sich eine Multiplikation von int32_t-Werten in C, C++ oder Java: Beim Überlauf wird einfach „herumgewickelt“.
Mit einer normalen Multiplikation a * b geht das nicht zuverlässig. JavaScript rechnet intern mit 64-Bit-Gleitkommazahlen (IEEE 754), die nur 53 Bit Mantisse haben. Ist das Produkt größer als 253, gehen die unteren Bits verloren, und ein nachgestelltes | 0 liefert dann ein falsches Ergebnis. Math.imul() berechnet die unteren 32 Bit dagegen immer exakt.
Typische Einsatzfälle sind Hash-Funktionen (FNV-1a, MurmurHash, xxHash), Pseudo-Zufallsgeneratoren (z. B. Mulberry32, xorshift), Prüfsummen, Portierungen von C-Code und Code, der zu asm.js oder WebAssembly-nahem JavaScript kompiliert wurde.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $a Pflicht | number | Erster Faktor. Wird per ToUint32 in eine 32-Bit-Ganzzahl umgewandelt. Nachkommastellen werden abgeschnitten, NaN und Infinity werden zu 0. |
|
| $b Pflicht | number | Zweiter Faktor. Wird genauso umgewandelt wie a. |
Rückgabewert
Beispiele
Grundlegendes Verhalten und Überlauf
console.log(Math.imul(2, 4)); // 8
console.log(Math.imul(-1, 8)); // -8
console.log(Math.imul(-2, -2)); // 4
console.log(Math.imul(0xffffffff, 5)); // 0xffffffff wird als int32 zu -1 → -5
console.log(Math.imul(0xfffffffe, 5)); // -2 * 5 → -10
console.log(Math.imul(3.7, 2)); // Nachkommastellen fallen weg → 6
console.log(Math.imul(2 ** 31, 2)); // Überlauf → 0
Unterschied zu (a * b) | 0 bei großen Produkten
const a = 0x7fffffff;
const b = 0x7fffffff;
// Gleitkomma-Produkt ist größer als 2^53 → untere Bits gehen verloren
console.log((a * b) | 0); // falsch
console.log(Math.imul(a, b)); // exakt: (2^31 - 1)^2 mod 2^32 = 1
32-Bit-Hash FNV-1a
const fnv1a = (str) => {
let hash = 0x811c9dc5; // FNV-Offset-Basis
for (let i = 0; i < str.length; i++) {
hash ^= str.charCodeAt(i);
hash = Math.imul(hash, 0x01000193); // FNV-Primzahl
}
return hash >>> 0; // als vorzeichenlose Zahl ausgeben
};
console.log(fnv1a('hello').toString(16));
Deterministischer Zufallsgenerator (Mulberry32)
const mulberry32 = (seed) => () => {
seed = (seed + 0x6d2b79f5) | 0;
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
const rand = mulberry32(42);
// Gleicher Seed → immer dieselbe Folge im Bereich [0, 1)
console.log(rand(), rand(), rand());
// Wichtig · Fallstricke
- Ergebnis ist vorzeichenbehaftet: Brauchst du einen Wert zwischen 0 und 232−1 (z. B. für eine Hex-Ausgabe), hänge
>>> 0an. - Kein Ersatz für normale Multiplikation: Für große Zahlen oder Kommazahlen liefert
Math.imul()absichtlich „falsche“ Werte, weil es auf 32 Bit kürzt. Für exakte große Ganzzahlen nimmBigInt. - BigInt geht nicht:
Math.imul(2n, 3n)wirft einenTypeError. Für 64-Bit-Arithmetik mit Überlauf gibt esBigInt.asIntN(64, a * b). - Leistung: Moderne Engines übersetzen
Math.imul()direkt in einen Maschinenbefehl zur Ganzzahl-Multiplikation. Für 32-Bit-Rechnungen ist das meist schneller als Umwege über Gleitkommazahlen. - Kompatibilität: Seit ES2015 in allen modernen Browsern und in Node.js vorhanden. Nur der Internet Explorer kennt die Methode nicht; dafür gibt es einen Polyfill, der die Faktoren in 16-Bit-Hälften zerlegt.