"间隔是空的",Lua math.random不适用于大数?

Hou*_*ter 5 random lua

我不知道这是Lua本身的错误还是我做错了什么.我无论如何都找不到任何关于它的东西.我正在使用Lua for Windows(Lua 5.1.4):

>return math.random(0, 1000000000)
1251258
Run Code Online (Sandbox Code Playgroud)

这将返回0到10000000000之间的随机整数,如预期的那样.这似乎适用于所有其他值.但如果我添加一个0:

>return math.random(0, 10000000000)
stdin:1: bad argument #2 to 'random' (interval is empty)
Run Code Online (Sandbox Code Playgroud)

任何高于此数字的数字都是相同的.

我试图弄清楚一个数字必须有多高才能导致这种情况发现甚至更奇怪的事情:

>return math.random(0, 2147483647)
-75617745
Run Code Online (Sandbox Code Playgroud)

如果值是2147483647那么它给出了负数.任何高于此值,它会抛出一个错误.任何低于它,它工作正常.

这是0b1111111111111111111111111111111二进制的,完全是31位二进制数字.我不确定这意味着什么.

gre*_*olf 9

这种意外行为(错误?)是由于如何math.random处理Lua 5.1中传递的输入参数.来自lmathlib.c:

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;
}
Run Code Online (Sandbox Code Playgroud)

正如你在C知道,一个标准int可以代表的数值-2,147,483,6482,147,483,647.添加+12,147,483,647您的使用情况一样,将溢出和周围包裹的价值给予-2,147,483,648.最终结果是否定的,因为您将正数乘以负数.

此外,由于溢出环绕,上述任何内容都2,147,483,647将失败luaL_argcheck.

有几种方法可以解决这个问题:

  • 升级到Lua 5.2.那个人已经通过将输入参数视为lua_Number相反来修复了这个问题.
  • 切换到没有此整数溢出问题的LuaJIT.
  • 使用修复和重新编译自己修补Lua 5.1源代码.
  • 修改您的随机范围,使其不会溢出.