jscl icon indicating copy to clipboard operation
jscl copied to clipboard

Simple multiplication gets wrong answer

Open ksaj opened this issue 4 years ago • 6 comments

(* 123456789 123456789) 15241578750190520

The answer should be 15241578750190521.

ksaj avatar Jun 20 '21 17:06 ksaj

Here's another example:

CL-USER> (* 99999995 99999995) 9999999000000024

The last digit should be a 5.

ksaj avatar Jun 20 '21 17:06 ksaj

JSCL represents all numbers as Javascript "number" (floats). There is no distinction between floats and integer, and no bignums.

This was a more unavoidable limitation when we started JSCL. Nowadays it would be feasible to use Javascript bigints when possible to differentiate them from numbers.

But it does require a bit of work on the compiler! It sounds like a fun project for sure.

An open question is if using bigint would have bad performance implications or if the engines optimize for small bigints :-)

We could make it optional by (at least temporarily) using some constructors for numbers with something like internals.n(25).

davazp avatar Jun 20 '21 19:06 davazp

I'm not a JS coder, so I was unaware of this limitation. The math should be coded instead of using "default" JS constructs once the numbers reach that tipping point, I suppose. It probably means there are a lot more examples like this, and probably examples that are off by more than one digit.

ksaj avatar Jun 20 '21 19:06 ksaj

Indeed. Luckily there is a way foward now at least!

Until then though, anything that goes out of this range will be wrong:

Number.MAX_SAFE_INTEGER // => 9007199254740991

and functions like integerp and floatp will give incorrect results on integers. (floatp 1.0) ; => NIL and (integerp 1.0) ; => T.

It's surprising how lot of code does still work considering those issues 🙂

davazp avatar Jun 21 '21 06:06 davazp

It's surprising how lot of code does still work considering those issues 🙂

Ugu;) Artifacts:

CL-USER> (floatp 1.0)
NIL
CL-USER> (floatp 1.00000000001)
T
CL-USER> (floatp 1.000000000001)
T
CL-USER> (floatp 1.000000000000001)
T
CL-USER> (floatp 1.0000000000000001)
NIL

sbcl

CL-USER> (1+  (expt 2 53))
9007199254740993
CL-USER> (expt 2 53)
9007199254740992

jscl

CL-USER> (1+  (expt 2 53))
9007199254740992
CL-USER> (expt 2 53)
9007199254740992

vlad-km avatar Jun 21 '21 19:06 vlad-km

I opened a WIP pull request to see what bignum support might look like at #404

davazp avatar Jun 22 '21 06:06 davazp