9

How can I emulate 32bit unsiged integers without any external dependencies in Javascript? Tricks with x >>> 0 or x | 0 don't work (for multiplication, they seem to work for addition / subtraction), and doubles lose precision during multiplication.

For example, try to multiply 2654435769 * 340573321 (mod 2^32). The result should be 1.

This answer has multiplication. What about addition / subtraction / division?

Here's a link to wolfram alpha, presenting the equation above.

Community
  • 1
  • 1
user1367401
  • 1,030
  • 17
  • 26

2 Answers2

3

A 32-bit unsigned int fits within Javascript's 64-bit float -- there should be no loss of precision when performing addition, subtraction, or division. Just mask with 0xffffffff to stay within a 32-bit integer. Multiplication goes beyond what fits, but you already have a solution for that.

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • However the precision may not be high enough after the multiplication, because to 32-bit integers multiplied can get a 64-bit integer, while the 64-bit floating number can only represent 53 significant bits. Is there a better way? – robbie fan Nov 07 '16 at 01:27
  • Beware there are still some terrible pitfalls like `(1 << 31).toString(16) === '-80000000'` (note sign). This is because [The left operand will be converted to a 32-bit integer, which means floating point numbers will be truncated, and number not within the 32-bit bounds will over-/underflow.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Left_shift) To work around that, use multiplication instead of shift, e.g. `(0x8000 * 65536)` instead of `(0x8000 << 16)` – jacobq Mar 14 '23 at 20:33
1

You can ape it with BigInts in 2020.

const u32mul = (x, y) => Number((BigInt(x) * BigInt(y)) & 0xFFFFFFFFn);

A sufficiently smart compiler should work this out, but I haven't benchmarked this, so proceed with caution.

The other alternative would of course drop into WebAssembly. If you need to be working at this level, I'd strongly advise it.

mseddon
  • 1,815
  • 17
  • 28