日期:2014-04-19 浏览次数:20568 次
找到了两个算法, 第一个很简单, 但可惜不是随机的, 第二个是典型的伪随机数算法, 可惜要用到2的几百万次方这样巨大的整数, 真痛苦
要是有UNIX上计算密码的源代码就好了
第一种做法:
f(k) = (k*F(N-1)) mod F(N)
其中,
k是一个序列号, 就是要取的那个数的顺序号
F(N)是这样一个序列 F(0) = 0, F(1) = 1, F(N+2) = F(N+1)+F(N) (for N>=0)
第二种做法
V = ( ( V * 2 ) + B .xor. B ... )(Mod 2^n)
N+1 N 0 2
V是要取的随机数, B是个种子, n是随机数的最大个数
原来这个问题, 很高难, 不少数学高手都为解决这个问题写了论文, 咳咳, 偶真是个白痴
呵呵, 效果肯定是不错啦, 因为用不到很大的表.至于应用是这样的, 比如, 你要给每个用户在注册的时候一个ID但有不希望用户在看到自己的ID的时候能知道其他用户的ID, 如果用SEQUENCE来生成ID的话, 一个用户只要把自己的ID减1就能得到其它用户的ID了. 所以要用随机数来做ID, 这样用户很难猜到其他用户的ID了.
当然主要的问题是, 随机数可能重复. 因此希望使用一个随机数做种子用它来确定一组"无规律"的自然数序列, 并且在这个序列中不会出现重复的自然数. 在这里使用的方法生成的序列并不是没有规律的, 只不过这个轨律很难被发现就是了.
Xn+1 = (aXn + b) mod c (其中, abc通常是质数)是一种被广泛使用的最简单的随机数发生算法, 有研究表表明这个算法生成的随机数基本上符合统计规律, JAVA, BORLAND C等用的都是这个方法, 一般只要保证第一个种子是真正的随机数就行了,
下面来说一下重复的问题,
上述方法会有可能出现重复, 因为当(aXn + b)有可能是同样的数或者说余数相同的数, 因此要想不重复就得变形
偶想到的方法是
Xn=(a*n + b) mod c n是一个在1到c之间的整数, a*n + b就是一个线性公式了, 且若n不同则a*n + b也不同, 它们除上质数c得到的余数也肯定不同, 因为 若不考虑a和b而只有n的时候, 每次的结果都是n,而线性公式, 只不过移动了这条直线的位置和斜率而已, 每个结果仍然不会相同的,
为了增加不可预计性, 偶又为上面那个公式设计了, 随机数种子, 于是就变成了这个样子
F(N)=(随机数*(N+随机数))MOD 一个质数
这样就能够产生 1到选定质数之间的一个"无规律"的自然数序列了, 只要改变随机数就能改变序列的次序
在应用的时候, 要把随机数种子和最后用到的序列号保存到一个表里, 每此使用的时候取出来算好, 再把序列号更新一下就可以了
具体地说, 就是可以建一个表来保存每个序列的随机数种子, 然后再为这个序列建一个SEQUENCE就行了
然后就
SELECT MOD(序列控制表.随机数*(SEQ.NEXTVAL+序列控制表.随机数)),序列控制表.质数)
FROM 序列控制表
WHERE 序列控制表.序列ID=XX
就OK了
注意 序列控制表.质数 决定了序列的范围