Losing precision in Lua - lua

I have a function in lua, which is given 2 vectors, return the lambda multiplier of first vector to second one, here is my code
function Math.vectorLambda( v1,v2 )
local v1Length,v2Length=math.sqrt(v1.x^2+v1.y^2),math.sqrt(v2.x^2+v2.y^2)
if v1Length==0 then
return nil
else
local dotProduct=v1.x*v2.x+v1.y*v2.y
print(dotProduct,v1Length,v2Length,math.abs(dotProduct)==(v1Length*v2Length))
if math.abs(dotProduct)==(v1Length*v2Length) then
if v1.x~=0 then
return v2.x/v1.x
else
return v2.y/v1.y
end
else
return nil
end
end
end
However, if
--this is what I get from terminal and I believe that it does not display the whole number--
v1={0.51449575542753,-0.85749292571254}
v2={-10,16.666666666667}
the output is
-19.436506316151 1 19.436506316151 false
which is saying the absolute value of dotProduct and v1Length*v2Length are not the same...
What is the reason for above, rather than I am blind? :(
BTW, the function is not stable..with exactly the same vectors, the function might has the same output except math.abs(dotProduct)==(v1Length*v2Length) gives true and hence return correct answer rather than nil, why?

Floats are tricky. You most likely have differences on the smaller decimal places (I don't know for sure, since I get true here). Try printing the numbers with a bigger precision, using a function like:
function prec_print(v, prec)
local format = '%.' .. prec .. 'f'
print(string.format(format, value))
end
In any case, you should almost never use == to compare floating point equality. For floats, it's quite easy to get false for simple things like a+b-b==a. What you should probably do is to check whether de difference of the two values is less than some threshold:
function almost_equal(float1, float2, threshold)
return math.abs(float1 - float2) <= threshold
end
But it's actually trickier than that (if, say, float1 and float2 are too far apart). Anyway, this read is mandatory for anyone working with floats: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Cheers!

Related

Attempt to perform arithmetic on a nil value

Here is the code im working with,
function Speedhack1()
boost = 1.5
if (readBytes('[_speed]') ~- nil) then
writeFloat ('[_speed]+DC', readFloat('[_speed]+DC')*boost)
writeFloat ('[_speed]+E0', readFloat('[_speed]+E0')*boost)
writeFloat ('[_speed]+E4', readFloat('[_speed]+E4')*boost)
end
end
createHotkey(Speedhack1, VK_UP)
function Speedhack2()
boost = 0.5
if (readBytes('[_speed]') ~- nil) then
writeFloat ('[_speed]+DC', readFloat('[_speed]+DC')*boost)
writeFloat ('[_speed]+E0', readFloat('[_speed]+E0')*boost)
writeFloat ('[_speed]+E4', readFloat('[_speed]+E4')*boost)
end
end
createHotkey(Speedhack2, VK_DOWN)
Ive defined speed and made pointers with the corresponding offsets my aob script to find speed works and the lua script gets executed but when pressing one of the hotkeys to start the function it gives me
Error:[string "function Speedhack1()
..."]:3: attempt to perform arithmetic on a nil value
if _speed has been defined and the offsets match i thought ~-nil would be the proper way to say "whatever the value is"
You probably meant to write ~= because ~- doesn't make much sense here. But it can also just be left out and you can write
if (readBytes('[_speed]')) then
This also checks whether it's not nil (or false)

How to make an auto text suggestion system?

If a user enters an invalid command then it returns the closest string to the user's input.
source = {"foo", "foo1"}
Suggest = function (input, source)
--do stuff
end
Thus when the user enters an undefined command "fo", for example it returns "foo".
Sorry if this is poorly explained, in a hurry.
You can use Levenshtein or Damerau–Levenshtein distance function to find commands closest to input. Here is a C library implementing both of these functions. Here is Levenshtein distance implemented in Lua.
The following function assumes distance is the distance function of choice. It takes optional radius argument to specify maximum distance from input to suggestion(you may not want to provide any suggestion if user entered something very strange, far from any existing commands). It returns an array of suggestions.
function suggest(input, source, radius)
local result = {}
local min_distance = radius or math.huge
for _, command in ipairs(source) do
local current_distance = distance(input, command)
if current_distance < min_distance then
min_distance = current_distance
result = {command}
elseif current_distance == min_distance then
table.insert(result, command)
end
end
return result
end
Note that this search algorithm is quite inefficient. It may or may not be a problem for you depending on number of commands and rate of searches.

How to return very long integer in Lua

I am trying to return very long integer number but my result returns as
"7.6561197971049e+016".
How do I make it return 76561197971049296 ?
local id64 = 76561197960265728
Z = string.match("STEAM_0:0:5391784", 'STEAM_%d+:%d+:(%d+)')
Y = string.match("STEAM_0:0:5391784", 'STEAM_%d+:(%d+):%d+')
--For 64-bit systems
--Let X, Y and Z constants be defined by the SteamID: STEAM_X:Y:Z.
--Let V be SteamID64 identifier of the account type (0x0110000100000000 in hexadecimal format).
--Using the formula W=Z*2+V+Y
if Z == nil then
return "none"
else
return Z*2+id64+Y
end
I installed lbc arbitrary precision now with this code
return bc.add(bc.number(id64),bc.number(2)):tostring()
it returns 70000000000000002 but if I delete 3 digits from id64 it displays correctly.
How can I get correct result without deleting the digits?
You need to use strings for long numbers. Otherwise, the Lua lexer converts them to doubles and loses precision in this case. Here is code using my lbc:
local bc=require"bc"
local id64=bc.number"76561197960265728"
local Y,Z=string.match("STEAM_0:0:5391784",'STEAM_%d+:(%d+):(%d+)')
if Z == nil then
return "none"
else
return (Z*2+id64+Y):tostring()
end
check out this library for arbitrary precision arithmetics. this so post might be of interest to you as well.
Assuming your implementation of Lua supports that many significant digits in the number type, your return statement is returning that result.
You're probably seeing exponential notation when you convert the number to a string or printing it. You can use the string.format function to control the conversion:
assert( "76561197971049296" == string.format("%0.17g", 76561197971049296))
If number is an IEEE-754 double, then it doesn't work. You do have to know how your Lua is implemented and keep in mind the the technical limitations.
If you have luajit installed, you can do this:
local ffi = require("ffi")
steamid64 = tostring(ffi.new("uint64_t", 76561197960265728) + ffi.new("uint64_t", tonumber(accountid)))
steamid64 = string.sub(steamid64, 1, -4) -- to remove 'ULL at the end'
Hope it helps.

Evaluating a math string in Corona Lua

I would like to evaluate a math string in my corona app. Right now I'm focusing on the trig functions, so let's let the example be the most difficult we're likely to face:
local expr = "2sin(4pi+2)+7"
My goal is for this to somehow be (either) evaluated as is with maybe a pi --> math.pi switch, or to even break it up. The breaking up would be much more difficult, however, since it COULD be as complicated a above, but could also just be sin(1).
So I would prefer to stay as close to the python eval(expr) function as possible, but if that can't happen, I am flexible.
The simplest way would be to replace sin with math.sin (pi with math.pi and so on), add missing multiplications signs, and run it through loadstring, but loadstring is not available in Corona environment.
This means you will need to write your own parser for these expressions. I found a discussion on Corona forums that may help you as a starting point: here, with some details and a demo here
This should do the trick, it is able to use the lua math functions without putting 'math.function' so just sqrt(100) works fine. I threw this together because I have seen this question asked way too many times. Hopes this helps :)
If you have any questions feel free to contact me at rayaman99#gmail.com
function evaluate(cmd,v) -- this uses recursion to solve math equations
--[[ We break it into pieces and solve tiny pieces at a time then put them back together
Example of whats going on
Lets say we have "5+5+5+5+5"
First we get this:
5+5+5+5 + 5
5+5+5 + 5
5+5 + 5
5 + 5
Take all the single 5's and do their opperation which is addition in this case and get 25 as our answer
if you want to visually see this with a custom expression, uncomment the code below that says '--print(l,o,r)'
]]
v=v or 0
local count=0
local function helper(o,v,r)-- a local helper function to speed things up and keep the code smaller
if type(v)=="string" then
if v:find("%D") then
v=tonumber(math[v]) or tonumber(_G[v]) -- This section allows global variables and variables from math to be used feel free to add your own enviroments
end
end
if type(r)=="string" then
if r:find("%D") then
r=tonumber(math[r]) or tonumber(_G[r]) -- A mirror from above but this affects the other side of the equation
-- Think about it as '5+a' and 'a+5' This mirror allows me to tackle both sides of the expression
end
end
local r=tonumber(r) or 0
if o=="+" then -- where we handle different math opperators
return r+v
elseif o=="-" then
return r-v
elseif o=="/" then
return r/v
elseif o=="*" then
return r*v
elseif o=="^" then
return r^v
end
end
for i,v in pairs(math) do
cmd=cmd:gsub(i.."(%b())",function(a)
a=a:sub(2,-2)
if a:sub(1,1)=="-" then
a="0"..a
end
return v(evaluate(a))
end)
end
cmd=cmd:gsub("%b()",function(a)
return evaluate(a:sub(2,-2))
end)
for l,o,r in cmd:gmatch("(.*)([%+%^%-%*/])(.*)") do -- iteration this breaks the expression into managable parts, when adding pieces into
--print(":",l,o,r) -- uncomment this to see how it does its thing
count=count+1 -- keep track for certain conditions
if l:find("[%+%^%-%*/]") then -- if I find that the lefthand side of the expression contains lets keep breaking it apart
v=helper(o,r,evaluate(l,v))-- evaluate again and do the helper function
else
if count==1 then
v=helper(o,r,l) -- Case where an expression contains one mathematical opperator
end
end
end
if count==0 then return (tonumber(cmd) or tonumber(math[cmd]) or tonumber(_G[cmd])) end
-- you can add your own enviroments as well... I use math and _G
return v
end
a=5
print(evaluate("2+2+2*2")) -- This still has work when it comes to pemdas; however, the use parentheses can order things!
print(evaluate("2+2+(2*2)"))-- <-- As seen here
print(evaluate("sqrt(100)"))
print(evaluate("sqrt(100)+abs(-100)"))
print(evaluate("sqrt(100+44)"))
print(evaluate("sqrt(100+44)/2"))
print(evaluate("5^2"))
print(evaluate("a")) -- that we stored above
print(evaluate("pi")) -- math.pi
print(evaluate("pi*2")) -- math.pi

Lua: How to set a variable to zero

I have variable that contains a number. While Lua allows variables to be set to nil, the variable then becomes toxic - destroying all code in its path.
If a variable contains a nil, I want it converted to a zero.
local score;
score = gameResults.finalScore;
I want to ensure that score contains a number, so I try:
local score;
score = tonumber(gameResults.finalScore);
but that doesn't work. So I try:
local function ToNumberEx(v)
if (v == nil) then
return 0
else
return tonumber(v)
end
local score;
score = ToNumberEx(gameResults.finalScore);
but that doesn't work. So I try:
local function ToNumberEx(v)
if (v == nil) then
return 0
else
return tonumber(v)
end
local score;
score = ToNumberEx(gameResults.finalScore);
if (score == nil) then
score = 0
end
That works, but defeats the purpose of having a function.
What is wrong with the function? I'm sure there is a perfectly reasonable and logical explanation - except to anyone who is familiar with programming languages.
score = tonumber(gameResults.finalScore) or 0
If the argument is already a number or
a string convertible to a number, then
tonumber returns this number;
otherwise, it returns nil.
Your code was good, except you didn't take into account what happens when gameResult.finalScore can't be converted to a number, if it was " " or "stuff" or a table than tonumber would return nil. None of your checks could detect that kind of situation.
If you really want to enforce that this variable gameResults.finalScore has this behavior (set to zero when receives any value different from a number), than you should take a look at Lua metatables.
You could create a metatable for gameResults, and "overwrite" the "index" and "newindex" methods of the metatable, checking the value for the finalScore field, and thus enforcing it's value to be on the desired ranges.
Not the best solution, but depending on your case, could be a good defensive practice against some other "evil developer" on the team. :-)
www.lua.org/pil/13.html (I'm not currently allowed to post more than 1 link) PiL 1 can help too, if you are still using Lua 5.0 or you want a more deep understanding of the metatables concept.

Resources