How are operators overloaded for numbers? I need this for replacing the standard floating point numbers in Lua with big floats (384 bit floats from Cephes) that I've added as a library without having to change Lua itself. The reason is that sometimes normal Lua doubles get mixed up with the big floats if you don't convert the Lua doubles to big floats first.
Can it be done with just some Lua code, or does Lua have to be changed (not necessarily a problem, but still undesirable)?
Related
I run Lua on a CPU without dedicated floating point HW, depending on SW emulation.
From luaopt.h I can see that some macros are set to double, but it does not clearly state when floats are used and its a little hard to track it.
If my script does simple stuff like:
a=0
a=a+1
for...
Would that involve a floating point operations at any level?
If no that's fine, but what is then the benefit to change macros to long?
(I tried of course but did not work....)
All numeric operations in Lua are performed (according to the default configuration) in floating point. There is no distinction made between floating point and integer, all values are simply numbers.
The actual C type used to store a Lua number is set in luaconf.h, and it is both allowed and even practical to change that to a suitable integral type. You start by changing LUA_NUMBER from double to int, long, or perhaps ptrdiff_t. Then you will find you need to tweak the related macros that control the conversions between strings and numbers. And, of course, you will likely need to eliminate most or all of the base math library since math.sin() and its friends and neighbors are not particularly useful over integers.
The result will be a Lua interpreter where all numbers are integers. The language will still allow you to type 3.14, but it will be stored as 3. Your code will likely not be completely portable to a Lua interpreter built with the standard configuration since a huge amount of Lua code casually assumes that floating point arithmetic is permitted, and remember that your compiled byte code will definitely not be compatible since byte code will store numbers as LUA_NUMBER.
There is LNUM patch (used, for example, by OpenWrt project which relies heavily on Lua for providing Web UI on hardware without FPU) that allows dual integer/floating point representation of numbers in Lua with conversions happening behind the scenes when required. With it most integer computations will be performed without resorting to FPU. Unfortunately, it's only applicable to Lua 5.1; 5.2 is not supported.
Why does Erlang not include arbitrary precision for math functions? I recently had to use math:pow(2,4333), and it throws an error. Why does Erlang not use libraries like GMP? Are there any plans to include it in the standard library? (Haskell uses it, [strike]even Java has bignums[strike]).
Thanks.
Update:
To add more perspective, I understand that it can be done using NIFs. I was solving problems from hackerrank in which the input uses larger numbers. pow/2 can be easily written in Erlang and it worked, but for larger computations, it would be slow.
Java returns double for pow so it does not work for Math.pow(2, 1024) which gives Infinity.
Erlang has bignums for integers but uses 64-bit IEEE standard floating point numbers. So while you can happily compute factorial(10000) with integers by default the math library uses floating point so math:pow(2, 4333) does not work.
Original Message:
I need to multiply two 64 bit numbers, but Lua is losing precision
with big numbers. (for example 99999999999999999 is shown as
100000000000000000) After multiplying I need a 64 bit solution,
so I need a way to limit the solution to 64 bits. (I know, if the
solution would be precise, I could just use % 0x10000000000000000,
so that would work too)
EDIT: With Lua 5.3 and the new 64 bit integer support, this problem doesn't exist anymore. Neat.
Lua uses double-precision floating points for all math, including integer arithmetic (see http://lua-users.org/wiki/FloatingPoint). This gives you about 53 bits of precision, which (as you've noticed) is less than you need.
There are a couple of different ways to get better precision in Lua. Your best bet is to find the most active such effort and piggy-back off it. In that case, your question has already been answered; check out What is the standard (or best supported) big number (arbitrary precision) library for Lua?
If your Lua distribution has packages for it, the easy answer is lmapm.
If you use LuaJIT in place of Lua, you get access to all C99 built-in types, including long long which is usually 64 bits.
local ffi = require 'ffi'
-- Needed to parse constants that do not fit in a double:
ffi.cdef 'long long strtoll(const char *restrict str, char **restrict endptr, int base);'
local a = ffi.C.strtoll("99999999999999999", nil, 10)
print(a)
print(a * a)
=> 3803012203950112769LL (assuming the result is truncated to 64 bits)
In my engine I have a Lua VM for scripting. In the scripts, I write things like:
stage = stage + 1
if (stage == 5) then ... end
and
objnum = tonumber("5")
if (stage == objnum)
According to the Lua sources, Lua uses a simple equality operator when comparing doubles, the internal number type it uses.
I am aware of precision problems when dealing with floating point values, so I want to know if the comparison is safe, that is, will there be any problems with simply comparing these numbers using Lua's default '==' operation? If so, are there any countermeasures I can employ to make sure 1+2 always compares as equal to 3? Will converting the values to strings work?
You may be better off by converting to string and then comparing the results if you only care about equality in some cases. For example:
> print(21, 0.07*300, 21 == 0.07*300, tostring(21) == tostring(0.07*300))
21 21 false true
I learned this hard way when I gave my students an assignment with these numbers (0.07 and 300) and asked them to implement a unit test that then miserably failed complaining that 21 is not equal 21 (it was comparing actual numbers, but displaying stringified values). It was a good reason for us to have a discussion about comparing floating point values.
I can employ to make sure 1+2 always compares as equal to 3?
You needn't worry. The number type in Lua is double, which can hold many more integers exactly than a long int.
Comparison and basic operations on doubles is safe in certain situations. In particular if the numbers and their result can be expressed exactly - including all low value integers.
So 2+1 == 3 will be fine for doubles.
NOTE: I believe there's even some guarantees for certain math functions ( like pow and sqrt ) and if your compiler/library respects those then sqrt(4.0)==2.0 or 4.0 == pow(2.0,2.0) will reliably be true.
By default, Lua is compiled with c++ floats, and behind the scenes number comparisons boils down to float comparisons in c/c++, which are indeed problematic and discussed in several threads, e.g. most-effective-way-for-float-and-double-comparison.
Lua makes the situation only slightly worse by converting all numbers, including c++ integers, into floats. So you need to keep it in mind.
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?
> print(string.format("%18.0f",1247687475123456))
1247687475123456
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.