但是执行几次后发现,每次的结果都是一样的,看起来这种随机数计算的结果都是一样的。
搜索下查到这种情况的原因:
http://blog.csdn.net/yanjun_1982/article/details/1329804
,引用下原文:
也许很多人会奇怪为什么使用LUA的时候,第一个随机数总是固定,而且常常是最小的那个值,下面我就简要的说明一下吧,说得不好,还请谅解。我现在使用的4.0版本的LUA,看的代码是5.0的,呵呵
LUA4.0版本中的自带函数库中有两个关于随机数的函数,一个是random,一个是randomseed。random有两个参数,用来设置随机数的范围,比如random(1,100)设置随机数的范围为1至100之间。由于C中所产生的随机序列是固定的,并且第一个随机数比较小,只有41。LUA重新设计了random函数,使得它可以产生范围固定的随机数,但由于LUA的random只是封装了C的rand函数,使得random函数也有一定的缺陷,那就是如果random的两个输入参数的值相差很小的时候,那么随机序列的第一个随机数就会和第一个输入参数很接近,比如第一次调用random(1,100)的时候,返回值肯定是1,只有相差大于799时,如random(1,800)第一次调用才会返回2,也是很接近1。
由于这个原因,为了实现真正的随机,那么第一次就不能让玩家调用random函数,不然玩家就可以获得一些低概率的东西了。比如if random(1,100) == 1 then ...... do,看起来是1%的的概率,但是第一次执行的时候是100%成立的,存在一定的隐患。解决这个问题的方法有两个,一就是第一次random函数不能让玩家执行,二就是使用randomseed先设一个随机种子。对于第一种方法,可能还是有一定的风险,毕竟随机序列还是固定的,玩家第一次调用random的时候还是得到有规律的返回值。第二种方法比较安全,在服务器启动的时候设置一个随机种子,让系统产生的随机序列不相同,但使用randomseed的时候也还要注意一个问题,那就是做种子的数要足够的大,大于10000就行了。不然randomseed所产生的随机序列的第一个值还是很小。原因是randomseed是直接封装了C的srand,如果种子的值太小,那么srand所产生的序列和默认序列(srand(1)所产生的序列)是相差不大的,序列的第一个值还是很小。
因此,只要在服务器启动的时候调用一下randomseed(GetTime())就可以解决这个问题了。
还要补充一下,LUA中产生随机数的算法还是有一些问题,比如执行random(1,3276700),它返回的值最后两位必为0。这是由LUA本身的随机函数算法决定的。
还是简要介绍一下LUA中random函数的实现方法吧,主要由源码中的下面两行实现:
lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
lua_pushnumber(L, (int)floor(r*(u-m+1))+m);
其中m为random函数的第一个参数,u为第二个参数。由上面的代码可以看出,如果u-l太小,那么当r也很小的时候,r*(u-m+1)就会很小(小于1),那么再经过floor运算,最经结果就是m。这就可以解释为什么random产生的第一个随机数常常会很接近m。再来看看当m为0,u为327670的时候会怎样。在上面的代码里,RAND_MAX是一个宏,它的值是32767,也就是C语言中rand函数可以返回的最大值(不同的操作系统可能会有不一样的最大值)。当m为0,u为327670的时候,那么返回值就是floor(r*(327671)+0),我们再假设LUA与平台无关并且rand不会返回32767(上面用%避免了这个问题),那么r就可以简化为rand()/RAND_MAX,代入上式为floor(rand()*327671/32767)+0,就算rand()的返回值是32766,最终的结果也只有327660.99996......,经过floor运算后,最后那位数必为0。呵呵,我叫这样的随机数就伪随机数中的伪随机数。实际上面的公式是不允许化简的,即不能简单地把r代入r*(u-m+1),至于为什么,呵呵,因为r的值并不是rand()/RAND_MAX的值,r是double类型的,所以它只是一个和rand()/RAND_MAX很接近的数。
搜索下解决方法:
http://blog.csdn.net/zhangxaochen/article/details/8095007
,引用下原文:
Lua 生成随机数需要用到两个函数:
math.randomseed(xx), math.random([n [, m]])
1. math.randomseed(n) 接收一个整数 n 作为随机序列种子。
2. math.random([n [, m]]) 有三种用法: 无参调用, 产生 (0,1) 之间的浮点随机数; 只有参数 n, 产生 1-n 之间的整数; 有两个参数 n, m, 产生 n-m 之间的随机整数
对于相同的随机种子, 生成的随即序列一定是相同的。所以程序每次运行, 赋予不同的种子很重要。很自然想到使用系统时间作为随机种子,即:
math.randomseed(os.time())
----然后不断产生随机数
for i=1, 5 do
print(math.random())
end
但是问题出来了, 如果程序运行时间, 你又在很短的时间内多次运行这个程序,那么你得到的随机序列会是几乎不变的。 像这样:
>lua -e "io.stdout:setvbuf 'no'" "test.lua"
0.71141697439497
0.060121463667714
0.067506942960906
0.8607745597705
0.60652485732597
>Exit code: 0
>lua -e "io.stdout:setvbuf 'no'" "test.lua"
0.71141697439497
0.060121463667714
0.067506942960906
0.8607745597705
0.60652485732597
>Exit code: 0
>lua -e "io.stdout:setvbuf 'no'" "test.lua"
0.7115085299234
0.38813440351573
0.6127201147496
0.59511093478195
0.9212927640614
>Exit code: 0
可以看到前两次运行的随机数都是一样的。究其原因,就是 os.time() 返回的时间是秒级的, 不够精确, 而 random() 还有个毛病就是如果 seed 很小或者seed 变化很小,产生的随机序列仍然很相似。比如:
math.randomseed(100)
print(math.random(1000))
math.randomseed(102)
print(math.random(1000))
两次赋予的 seed 分别是 100, 102 但是random 生成的第一个随机数却是一样的。因此“短时间内多次运行程序” 这样的需求下 os.time 还真不大好。可是又没有比 time 函数更方便的种子生成器, 怎么办呢?
可以这样:
math.randomseed(tostring(os.time()):reverse():sub(1, 6))
就是把 time返回的数值字串倒过来(低位变高位), 再取高位6位。 这样, 即使 time变化很小, 但是因为低位变了高位, 种子数值变化却很大,就可以使伪随机序列生成的更好一些
Lua获取随机数函数:math.random ([m, n]) 该函数有三种用法1.random():返回0到1之间的一个伪随机数 2.random(n):返回1到n之间的伪随机整数3.random(m, n):返回m到n之间的伪随机整数
机会-用于生成
随机数
据的库
Chance是的端口,该库是用于为各种情况生成
随机数
据的库。 但是,这不是一个完美的端口,因为它不支持原始库的整个API,并且并非所有函数的行为方式都相同,例如
Lua
函数chance.float()返回的数字与原始库的chance.floating()在不同的范围内。 chance.floating() 。
机会需要
Lua
5.1或更高版本,或 2.0或更高版本。
只需将chance.
lua
放在包路径中的require()可以找到它的地方,然后像这样使用库:
local chance = require ( " chance " )
在chance.
lua
上运行将创建一个doc/目录,其中包含有关库API的详细信息。
如果可用,则在项目目录中运行tup将…
运行LDoc创建文档。
通过测试代码中的任何错误。
通过在chance.spe
Lua
错误处理
程序运行中错误处理是必要的,在我们进行文件操作,数据转移及web service 调用过程中都会出现不可预期的错误。如果不注重错误信息的处理,就会造成信息泄露,程序无法运行等情况。
任何程序语言中,都需要错误处理。错误类型有:
语法错误通常是由于对程序的组件(如运算符、表达式)使用不当引起的。一个简单的实例如下:
-- test.
lua
文件
a == 2
以上代码执行结果为:
lua
: test.
lua
:2: syntax error near '=='
正如你所看到的,以上出现了语法错误,一个 “=” 号跟两个 “=” 号是有区别
– 将os.time()
获取
的系统秒数数值翻转(低位变高位),再取高6位,这样即使time变化很小
– 由于低位变高位,数值就会变化很大,这样1秒内进行多次运行的话,效果会好些
local next = tostring(os.time()):reverse():sub(1, 6)
math.randomseed(next )
Lua
生成
随机数
需要用到两个函数:
math.randomseed(xx), math.random([n [, m]])
1. math.randomseed(n) 接收一个整数 n 作为随机序列种子。
2. math.random([n [, m]])
在一个程序启动时,默认固定以1为种子初始化
随机数
发生器,也就是说每次程序启动运行返回的都是固定顺序的伪
随机数
序列.
如果需要每次启动都返回不同的
随机数
序列则可以通过调用math.randomseed(os.time()) 手动设定种子.
给
随机数
设置
随机数
种子:math.randomseed(xx)
lua
对
随机数
种子也是有一定要求的:不能太相近
lua
中的os.time()是基于秒的,不太满足
lua
对
随机数
种子的要求(如果设置
随机数
种子的频率太高的话)
解决方案:
把 os.time()返回的数值字串倒过来再取高位7位。 这样,即使 os.time...
唯一的创新是seed 参考时间+ 一个
随机数
,保证每次请求的uuid 都不一样
math.randomseed(os.time()+math.random(1,1024*1024))
function guid(uid)
math.randomseed(os.time()+math.random(1,1024*1024))
local seed={'e','1','2','3','4','5','6','7','8','9','a...
这也是我从别的地方看来的,思路是先生成1到10的顺序序列,然后进行10次循环
循环中 产生一个1到10的
随机数
,然后进行两数交换,其实也很简单,看下就知道了
function tigerMachine:getNumList(len)
local rsList = {}
for i = 1,len do
table.insert(rsList,i)
```c++
lua
_getglobal(L, "
lua
_func"); //
获取
全局函数
lua
_func
lua
_pushinteger(L, 123); // 压入参数
lua
_pushstring(L, "hello world");
if (
lua
_pcall(L, 2, 1, 0) !=
LUA
_OK) // 调用函数
fprintf(stderr, "%s",
lua
_tostring(L, -1));
lua
_pop(L, 1);
int result =
lua
_tointeger(L, -1); //
获取
返回值
lua
_pop(L, 1);
printf("result=%d\n", result);
5. 关闭
Lua
状态机:
```c++
lua
_close(L);
上面的例子中,假设
Lua
脚本文件 test.
lua
中定义了一个名为
lua
_func 的函数,该函数接受两个参数,一个整数和一个字符串,返回一个整数。C++ 代码中调用该函数时,先
获取
全局函数
lua
_func,然后将参数压入栈中,最后调用函数并
获取
返回值。
Lua
C API 还提供了很多其他的函数和操作
Lua
数据类型的接口,具体可以参考
Lua
官方文档。