Skip to content

100000000000000000000000.000000000000001 is less precice than qjs/V8

I was trying out this package to fuzz typescript-go's JS number implementation, which currently shells out to Node.

For the value 100000000000000000000000.000000000000001, it seems like the ported QuickJS Go code in this package loses precision. Running:

package main

import (
	"fmt"

	"modernc.org/quickjs"
)

func main() {
	vm, err := quickjs.NewVM()
	if err != nil {
		panic(err)
	}
	defer vm.Close()

	r, err := vm.Eval(`100000000000000000000000.000000000000001`, quickjs.EvalGlobal)
	if err != nil {
		panic(err)
	}
	fmt.Println(r)

	r, err = vm.Eval(`+"100000000000000000000000.000000000000001"`, quickjs.EvalGlobal)
	if err != nil {
		panic(err)
	}
	fmt.Println(r)

	r, err = vm.Eval(`(100000000000000000000000.000000000000001).toString()`, quickjs.EvalGlobal)
	if err != nil {
		panic(err)
	}
	fmt.Println(r)
}

Nets:

1e+23
1e+23
1e+23

Yet QuickJS says:

QuickJS-ng - Type ".help" for help
qjs > 100000000000000000000000.000000000000001
1.0000000000000001e+23
qjs > +"100000000000000000000000.000000000000001"
1.0000000000000001e+23
qjs > (100000000000000000000000.000000000000001).toString()
'1.0000000000000001e+23'
qjs > 

V8 says:

V8 version 14.3.101
d8> 100000000000000000000000.000000000000001
1.0000000000000001e+23
d8> +"100000000000000000000000.000000000000001"
1.0000000000000001e+23
d8> (100000000000000000000000.000000000000001).toString()
"1.0000000000000001e+23"
d8> 

(I'm using QuickJS-ng here out of convenience, but the above is how QuickJS behaves in https://bellard.org/jslinux/vm.html?url=alpine-x86.cfg too.)