lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Mon, Jun 6, 2011 at 14:57, Justin Cormack
<justin@specialbusservice.com> wrote:
> On Sat, Jun 4, 2011 at 11:48 PM, Alexander Gladysh <agladysh@gmail.com>
> wrote:

>> Additionally, a plea for help: can some guru please help me with this
>> issue, with math.random() returning values outside of [0, 1)?

>> http://code.google.com/p/lua-alchemy/issues/detail?id=127

> I can't reproduce this under Linux or Mac OS.

Well, I cannot either — it reproduces only inside Lua Alchemy.

Here is a test case:
https://github.com/lua-alchemy/lua-alchemy/blob/v0.3/test/FluintLuaAlchemyTests/src/wrapperSuite/tests/TestLuaBased.as#L100-127

You may paste Lua code from the test to the Demo here:

http://lua-alchemy.googlecode.com/svn/trunk/demo/index.html

If you press Run, you'll see:

=== Error ===
luaDoString:10: 19637 bad a 1.0000005871999
stack traceback:
	[C]: in function 'error'
	luaDoString:10: in main chunk

> The source code in 5.1.4 below explicitly allows for the case of an odd
> underlying implementation, and has done since at least 5.0.

Well, the underlying implementation does not get much more odd — it is
Adobe Flash VM... :-)

> So I think the only way for this to happen would be if Lua was built with
> single precision float as the number type, as 2^29 in your example and
> RAND_MAX are both outside the precision of a single precision float.

Well, to the best of my knowledge, Lua Alchemy is built with
LUA_NUMBER as double:

https://github.com/lua-alchemy/lua-alchemy/blob/master/alchemy/lib/lua51/src/luaconf.h#L505

The demo certainly works with these values:

print = as3.makeprinter(output)
print(536870912, 2147483647) --> 536870912 2147483647

> I dont have a single precision build to see exactly where it fails, but I would put
> some debug code in math_random to determine where the rounding issue is,
> depending where the test code is actually failing...

> static int math_random (lua_State *L) {
>   /* the `%' avoids the (rare) case of r==1, and is needed also because on
>      some systems (SunOS!) `rand()' may return a value larger than RAND_MAX
> */
>   lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
>   switch (lua_gettop(L)) {  /* check number of arguments */
>     case 0: {  /* no arguments */
>       lua_pushnumber(L, r);  /* Number between 0 and 1 */
>       break;
>     }
>     case 1: {  /* only upper limit */
>       int u = luaL_checkint(L, 1);
>       luaL_argcheck(L, 1<=u, 1, "interval is empty");
>       lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */
>       break;
>     }
>     case 2: {  /* lower and upper limits */
>       int l = luaL_checkint(L, 1);
>       int u = luaL_checkint(L, 2);
>       luaL_argcheck(L, l<=u, 2, "interval is empty");
>       lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */
>       break;
>     }
>     default: return luaL_error(L, "wrong number of arguments");
>   }
>   return 1;
> }

Thank you for your help,
Alexander.