views:

414

answers:

2

I'm dealing with timestamps in Lua showing the number of microseconds since the Epoch (e.g. "1247687475123456").

I would really like to be able to print that number in all its terrible glory, but Lua insists on printing it in scientific notation. I've scoured the available documentation about printing a formatted string, but the only available commands are "Print in scientific notation (%e/%E)" and "Automatically print in scientific notation if the number is very long (%g)". No options seem to be available to print the number in its normal form.

I realize that I could write a function that will take the original number, do some dividing by 10 and print the digits in a loop but that seems like an inelegant hassle. Surely there's some way of doing this that's built in to the language?

+2  A: 
> print(string.format("%18.0f",1247687475123456))

1247687475123456

Doug Currie
You can omit the width; "%.0f" will use exactly as many digits as needed.
Nathan Kitchen
/facepalm!Man, I tried all manner of format strings but never considered the floating-point option. Thanks!
Zack
+1  A: 

Lua as usually configured uses your platform's usual double-precision floating point format to store all numbers. For most desktop platforms today, that will be the 64-bit IEEE-754 format. The conventional wisdom is that integers in the range -1E15 to +1E15 can be safely assumed to be represented exactly.

In any case, the string.format() function passes its arguments through (with some minor tweaks) to the platform's implementation of printf(). The format string understood by printf() includes %e and %E to force "scientific" notation, and %f to force plain decimal notation. In addition, %g and %G choose the shortest notation.

For example:

E:\...>lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> a = 1e17/3
> print(string.format("%f",a))
33333333333333332.000000
> print(string.format("%e",a))
3.333333e+016
> print(string.format("%.0f",a))
33333333333333332

Note that if the value fits within a 32-bit signed integer range, you can also use the %d format. However, results are not well defined if the value exceeds that range. System timestamps in microseconds are likely to exceed the 32-bit range.

If 16 decimal digits is not enough precision, there are several choices available for increased precision.

First, it would not be difficult to package a true 64-bit integer in a userdata along with a suitable set of arithmetic metamethods. This gets discussed occasionally on the Lua mailing list, but I don't recall seeing a completed module released by anyone.

Second, one of the Lua authors has released two modules supporting arbitrary precision arithmetic: lbc and lmapm. Both are found at that page.

Third, casual searching in Google readily turns up several other math library wrappers.

RBerteig