lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2015-08-19 5:34 GMT+02:00 Daurnimator <quae@daurnimator.com>:
> Lua 5.3 doesn't seem to accept fractional components when passing a base
>
> $ lua5.1 -e 'print(tonumber("9.0", 10))'
> 9
> $ lua5.3 -e 'print(tonumber("9.0", 10))'
> nil
> $ lua5.3 -e 'print(tonumber("9.0"))'
> 9.0

This already is true for Lua 5.2.

> Lua 5.3 performs overflow/wraparound on large numbers... but only with
> limited precision.
>
> $ lua5.1 -e 'print(tonumber("99999999999999999999999999999999999999999999999999999999999999999999999999999999"))'
> 1e+80
> $ lua5.3 -e 'print(tonumber("99999999999999999999999999999999999999999999999999999999999999999999999999999999"))'
> -1
> $ lua5.1 -e 'print(tonumber("999999999999999999999999999"))'
> 1e+27
> $ lua -e 'print(tonumber("999999999999999999999999999"))'
> -6930898827444486145
>
> Are these behaviours intentional?

They are exactly what you would get if you used that string in Lua source.

> s=9999999999999999999999999999999999999999999999999999999999999999
> s
-1

> Should these changes from 5.1/5.2 be documented?

The first one (which is a change only from 5.1) is documented.

>From the 5.2/5.3 manual:

~~~
When called with base, then e must be a string to be interpreted as
an integer numeral in that base. ... If the string e is not a valid numeral
in the given base, the function returns nil.
~~~

The second one is not a tostring issue, but deals more generally with
numerals that are lexically integers but not representable in 64 bits.

The manual makes only the lexical distinction:

~~~
A numeric constant with a fractional dot or an exponent denotes
a float; otherwise it denotes an integer.
~~

You have a point here. But documenting it does not go far enough:
it should be changed in Lua 5.3.2. While not technically a bug,
this is an totally unnecessary gotcha.

It is one thing for overflows to occur as a result of arithmetic
operations: decades of teaching of computer basics prepare
one for that. But string-to-number conversion, whether in
tostring() or load(), can easily check that a lexical integer is
in range (whatever "range" means for the current luaconf.h)
and should give an error otherwise.