Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test for -1.#IND (indeterminate) in Lua?

Tags:

nan

ieee-754

lua

Irrelavent justification for the question:

i'm getting an error calling Lua format:

integer overflow attempting to store -1.#IND

The variable's type(n) really is a number, and i can format it as a string (i.e. %s), but it's not a number, e.g.:

print(string.format("value=%s, type=%s", n, type(n)));

for the NaN value returns:

value=-1.#IND, type=number

i want to fix this, but i have no idea who is generating this NaN (Lua has no debugger).

So i'm left with having to throw a lot of asserts all over the code until i can pin down to the source of this intermittent NaN value.

But i can't find any condition that traps it, and Lua doesn't have isnan(x).

Question:

How can i test a number for -1.#IND in Lua?

Update:

i tried:

if (n ~= n) then
   print(string.format("NaN: value=%s, type=%s", n, type(n)));
else
   print(string.format("value=%s, type=%s", n, type(n)));
end;

and it prints

value=-1.#IND, number

Update Two: Just in case i missed something, my actual code is:

    if (oldValue ~= oldValue) then
        print(string.format("Is NaN: labelNumber=%d, formatString=\"%s\", oldValue=%s (%s)", labelNumber or 0, formatString or "nil", oldValue or "nil", type(oldValue)));
    else
        print(string.format("Is not NaN: labelNumber=%d, formatString=\"%s\", oldValue=%s (%s)", labelNumber or 0, formatString or "nil", oldValue or "nil", type(oldValue)));
    end;

And the faulty value outputs:

Is not NaN: labelNumber=4, formatString="%d", oldValue=-1.#IND (number)

Update Three

Still trying to solve this problem, i just noticed the absurdadity of reality:

function isnan(x)
   if type(x) ~= "number" then
       return false; --only a number can not be a number
   end;

   ...
end;
like image 530
Ian Boyd Avatar asked Aug 24 '12 01:08

Ian Boyd


1 Answers

n ~= n may work (with the caveats described in Mud's answer), but a more portable one may be:

function isnan(n) return tostring(n) == tostring(0/0) end

Those who are concerned about division by zero (as in Ian's comment; although I haven't seen it in practice) can use an alternative version:

function isnan(n) return tostring(n) == tostring((-1)^.5) end

Full function:

--local nanString = (tostring((-1) ^ 0.5)); --sqrt(-1) is also NaN. 
--Unfortunately, 
--  tostring((-1)^0.5))       = "-1.#IND"
--  x = tostring((-1)^0.5))   = "0"
--With this bug in LUA we can't use this optimization
local function isnan(x) 
    if (x ~= x) then
        --print(string.format("NaN: %s ~= %s", x, x));
        return true; --only NaNs will have the property of not being equal to themselves
    end;

    --but not all NaN's will have the property of not being equal to themselves

    --only a number can not be a number
    if type(x) ~= "number" then
       return false; 
    end;

    --fails in cultures other than en-US, and sometimes fails in enUS depending on the compiler
--  if tostring(x) == "-1.#IND" then

    --Slower, but works around the three above bugs in LUA
    if tostring(x) == tostring((-1)^0.5) then
        --print("NaN: x = sqrt(-1)");
        return true; 
    end;

    --i really can't help you anymore. 
    --You're just going to have to live with the exception

    return false;
end
like image 141
Paul Kulchenko Avatar answered Nov 15 '22 23:11

Paul Kulchenko