lua-users home
lua-l archive

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



On Sun, Sep 5, 2010 at 3:42 PM, Andre Leiradella <andre@leiradella.com> wrote:
 On 05/09/2010 03:15, Florian Weimer wrote:
* Rob Kendrick:

On Sat, Sep 04, 2010 at 10:54:59PM +0200, Florian Weimer wrote:

It could be argued that tostring is lossy for tables, so it can be
lossy for numbers, too.
Surely converting a floating point number to a string like this is
never not going to be lossy?
The default conversion in Lua (that is, tostring) is lossy,
unfortunately.

I'm having exactly the same problem with the serialization of floats and doubles to JSON (C++, not Lua.)

If the numbers are not supposed to be hand edited, the %a format specifier creates a lossless (depending on the precision used) hexadecimal ASCII representation of doubles that can be transformed back to double by strtod. It's a one line change in lstrlib.c, function str_format:

       case 'e':  case 'E': case 'f':
       case 'g': case 'G': case 'a': { // %a format specifier added
         sprintf(buff, form, (double)luaL_checknumber(L, arg));
         break;
       }

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print(string.format('%.13a', 0.1)) -- 13 is large enough to represent all significand bits
0x1.999999999999ap-4

Which is 1.999999999999a * 2^-4. And tonumber already converts it back to double:

> print(tonumber('0x1.999999999999ap-4'))
0.1

Unfortunately the lexer doesn't like the hexadecimal point but patching it must be easy:

> a=0x1.999999999999a0p-4
stdin:1: malformed number near '.999999999999a0p'

I am attaching a patch for anyone interested that does just that. Apply against stock 5.1.4.
 
Doubles have 52 bits to represent the significand, so 52/4=13 in the %a specifier is enough to represent all of its bits. The implicit 1 before the significand (0 in denormals) is not part of the fraction so it does not count in the 13 digits after the point.

It's a shame I can't use this format in JSON, its specification doesn't allow hexadecimal numbers.

Cheers,

Andre


Attachment: lua-5.1.4-hexfloat.patch
Description: Binary data