You seemed to have jumped from talking about integers to floating point!
And the example you have given is a problem with all floating point implementations, not just Javascript. You will get that exact same answer in C, Java, etc.
The only way to avoid this is to represent rational numbers directly, without simplification. For example:
There are no integers in js, all numbers are floats. What you want to do is represent all values as integers choosing an arbitrary precision, then only do integer math.
In the example given, using node-bignum and assuming our precision is a thousand of a cent:
big(30000).mul(3) => 90000
Of course you'd get the same result in plain javascript with these numbers, but then you'd have to handle everywhere an operation could return decimals, and using bignum you have "unlimited" precision > 52bits.
I agree with what you are saying. It's just that you gave a floating point multiplication example, where an integer multiplication with overflow would have been a relevant example.
Here's a relevant example,
2^26 * 2^26 == 2^52
may not hold in javascript because it only supports 52 significant binary digits. Whereas other languages usually support 64 significant binary digits.
And the example you have given is a problem with all floating point implementations, not just Javascript. You will get that exact same answer in C, Java, etc.
The only way to avoid this is to represent rational numbers directly, without simplification. For example: