lua-users home
lua-l archive

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


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

Alexander.


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

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.

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. 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;
}