软件生成真随机数组的一种方案
各种文件都以字节为单位,所以我们研究以字节为单位的随机数组即可,字节的取值 0 - 255,它们是随机数组的元素,建造一个256个元素没有重复元素的小数组,称之为单元数组,这样的单元有256!个大约有8.7×10的502次方之多。我们通过变换数组成员的位置获得新的单元,将生成的各单元连接起来组成大数组。
一、随机交换单元数组的成员位置:
(1)借助于随机函数可以完成这种交换,方法是这样,用C语言描述
unsigned int n1; //记录数组的序号
unsigned char ch; //临时记录数组成员的数值
unsigned char dy[256] = //初始单元数组{0x51,0xe4,0x2e,0x9a,0x47,0xd4,0x3e,0x2b,0x59,0x43,0xc2,0xc9,0x92,0x4d,0xdf,0xfb,0xdc,0xe8,0xff,0x45,0x27,0x1b,0x4b,0xca,0x81,0x8a,0x89,0x78,0xaf,0x6a,0x2c,0x10,0xc0,0x97,0xa7,0x00,0x1f,0x55,0x1c,0x21,0x49,0x58,0xa0,0xd2,0x0e,0x13,0x40,0xb6,0x86,0x69,0xfd,0xde,0x99,0x57,0x76,0xee,0xb1,0x01,0xa8,0xd1,0x39,0x02,0x4c,0x9e,0xe6,0x22,0xdd,0x05,0x08,0x75,0xc6,0xd8,0x7a,0xcc,0x8d,0x37,0x70,0x8c,0x72,0x32,0x6c,0xa9,0x6f,0x30,0x7b,0x80,0x6b,0x62,0xd0,0xec,0x9b,0x61,0xb9,0x52,0x93,0x74,0xb4,0xfc,0x53,0xe1,0x06,0xbd,0x41,0xcb,0x7f,0x36,0x25,0x35,0x46,0x77,0x54,0x73,0xf6,0x85,0x28,0xf0,0x26,0xb3,0x6e,0xac,0xf4,0xe2,0x90,0x88,0xce,0x71,0xcd,0x9c,0x09,0x18,0x9f,0xf2,0x4f,0x1d,0x03,0xc7,0xa2,0x0d,0xd7,0xbb,0xd9,0x17,0x33,0x19,0x82,0xbf,0x9d,0x4a,0x1a,0x94,0xef,0x7d,0x3b,0x48,0xc1,0x7e,0x24,0x15,0x5a,0x3d,0xc8,0x0b,0xaa,0x83,0x29,0x38,0x5d,0xe3,0x14,0x67,0xa5,0x23,0xbe,0x11,0xe5,0xab,0x79,0xda,0x8b,0xe9,0x44,0x1e,0xa3,0x31,0x95,0x84,0xbc,0xf9,0xcf,0x42,0xfe,0x2d,0x68,0xae,0x64,0xb0,0x04,0x07,0x16,0xf7,0xc4,0x34,0xdb,0x0f,0x8f,0x0c,0x3c,0xf5,0xe0,0xb5,0x66,0xd6,0x5e,0x65,0xad,0x60,0x2a,0x12,0x20,0x2f,0x87,0x6d,0x3a,0xd5,0x8e,0xb7,0x5c,0x5f,0x4e,0xf1,0xeb,0xc5,0x96,0xa6,0x98,0xba,0x56,0xf8,0xa1,0x0a,0xb2,0xa4,0xb8,0x91,0xed,0x7c,0xea,0xf3,0x3f,0x50,0xc3,0x63,0xe7,0xfa,0xd3,0x5b};
for(int i=0;i<256;i++) //完成一次单元数组的排序
{
n1 = rand()%256;
ch = dy[n1];
dy[n1] = dy[i];
dy[i] = ch;
}
如上可见,随机函数rand()产生的数值取模256后的值作为序号n1,将dy[n1]和dy[i]的数值交换,经过循环后单元数组的内容全变了,新的单元数组生成了。
(2)通过单元数组自身完成交换
for(int i=0;i<256;i++)
{
n1 = (dy[n1] + dy[i] + i)%256;
ch = dy[n1];
dy[n1] = dy[i];
dy[i] = ch;
}
因为单元数组本身就是随机数,当然可以利用来生成新的数组,当然也可以用前一组单元来排序。根据小数组试验得知,无限的做下去是不行的,可能产生循环。但256个元素的单元做2的32次方个也就是4.29G个循环,没有发现重复单元的产生。为了避免重复,不让它进行太多的循环。
二、生成随机数组
我们知道可以从计算机的时间得到一个不大的真随机数,为什么这样说,因为数值的前面总是一样的,而只能利用变化的部分。得到来自时间的真随机数后,经计算让它作为我们用到的随机函数的种子。然后利用随机函数加工初始单元数组见一、(1),完成后用一、(2)的方式进行10000次循环,生成10000个单元,将单元连接起来组成结果数组,现在数组长度有2.56M字节了,然后再取一个来自时间的真随机数(当然也可以取前面数组的某些数值组成种子)作为随机函数种子然后作用于数组,再生成下一个10000个单元...直到够用为止,可见随机函数的利用率是很低的,用256个字节的随机函数数值生成2.65M个字节的数组。这里10000是任意的大些小些都无所谓。由于随机函数起点是随机选取的,随机函数的周期影响不到此种方法,如果画蛇添足的话可选用大周期随机函数。
三、数组形成原理
这种方法生成随机数组本质上是利用了热力学第二定律也就是熵增加原理,对数组序列的随机排序只能使其越来越混乱,而不能越搅合越有规律。
这样形成的随机数组比来自物理现象的数值要更好一些,来自物理现象的数值往往有一些缺陷,例如连续数值相同,小规模的相似等,需要修正才能用,而这个不会有那些问题。