Jump to content
  • Advertisement
Sign in to follow this  
medevilenemy

#Nan And Other Strange Float Values

This topic is 2718 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, I recently added a lua interpreter to a project of mine, and set up a binding between it, and my message dispatcher. It seems to work perfectly in all cases I've tried so far, except when one of the arguments passed to the function is a non-zero whole numbered float (1.0, 2.0, 3.0, etc). These arguments work fine in the direct message dispatcher function, so somewhere between lua and there the value must be getting corrupted (gets turned into something like 1.#nan or some silly randomish value (2.[somethinghere]e[somethingrandom]). Any idea what I'm doing wrong? (alternatively, any idea how to do it better?) Thanks!

Here's the code for the binding function:
static int luabind_DispatchMessage(lua_State *L)
{
// Step one, figure out how many arguments I was called with
int argc = lua_gettop(L);
int i;

int type;
int temp1 = 0;
float temp2 = 0;

void *args[] = {NULL, NULL, NULL, NULL, NULL};

for(i = 1; i <= argc; ++i)
{
if(i == 1) // If this is the first argument, it must be the TYPE argument
{
type = (int)lua_tonumber(L, i);
}
else
{
if(lua_isnumber(L, i) == 1) // If this is a number
{
temp2 = lua_tonumber(L, i);
if(fmod(temp2, 1) == 0) // If this looks like an integer
{
temp1 = (int)temp2;
args[i-2] = (void *)temp1;
}
else // If this is actually a float
{
args[i-2] = ftov(temp2);
}
}
else if(lua_isstring(L, i) == 1) // If this is a char or a string
{
args[i-2] = (void *)lua_tostring(L, i);
}
}
}

Dispatch_Message(type, args[0], args[1], args[2], args[3], args[4]);

return 0;
}

Share this post


Link to post
Share on other sites
Advertisement
#nan = Not-A-Number

http://en.wikipedia.org/wiki/NaN

or some silly randomish value (2.[somethinghere]e[somethingrandom]). [/quote]
Sounds like E-Notation (or 'Scientific notation'). It may not be corrupt, just displayed in a format you aren't used to. (But it could ofcourse be corrupt AND displayed in a format you aren't used to).

http://en.wikipedia.org/wiki/E_notation#E_notation

I'm not familiar enough with E-Notation to help you beyond that.

Share this post


Link to post
Share on other sites
I suspect the problem is in one of two places:

Possibility 1) Mathematically, 1.0/2.0 and the like are integers and so probably trigger the integer condition in the code I posted. On the receiving end of the messaging system, this is converted (for messages that expect a float in a given position) to a float via a (float &) cast. Maybe that is unsafe?

Possibility 2) the return value of lua_tonumber (which is a lua_number which is a typedef of double) perhaps doesn't like being cast to a float?

Here is the code for ftov(), in case anyone finds it suspect.
void* ftov(float val)
{
DWORD tmp = *(DWORD *)&val;
return (void *)tmp;
}

Share this post


Link to post
Share on other sites
Through a little strlen trickery, I have made it such that the code now handles numbers like 1.0/2.0/3.0 properly if they are quoted in the lua script (because otherwise they would be truncated by lua_tostring. Not a perfect solution, but good enough for now.

Share this post


Link to post
Share on other sites
One obvious issue you'll run into is that in your Dispatch_Message function you'll need to interpret those void* elements as either a float or an integer, presumably based on the type. If your floating point value that you want to pass happens to end up as say 1.0 it'll be passed as an integer and handled the other end as a float, which probably isn't what you want and could be the source of those NaNs.

There's two obvious ways round that:

1. Pass all numbers as doubles like lua does. Not very convenient but should work. You'll have to change the argument types from void* to 64-bit ones to make that work.
2. Add a format string of some kind so you can use the proper argument types. This could be looked up based on the type parameter. For example:


static const char *dispatch_message_format_strings[NUM_TYPES] = { "iifsi", "siiii", ....};

switch (dispatch_message_format_strings[type][i-2])
{
case 'f': args[i-2] = ftov(lua_tonumber(L, i)); break;
case 'i': args[i-2] = (void*)((int)lua_tonumber(L, i)); break;
case 's': args[i-2] = (void *)lua_tostring(L, i); break;
default: assert(0); break; // Invalid format string
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!