用“序列数交换法”产生真随机数组

                                                    用“序列数交换法”产生真随机数组
               “序列数交换法”是将有规律的数组,通过任意交换数组的序列号,而形成随机数的方法。
               理论根据是热力学第二定理的推论“熵增加原理”,在自然作用下,从有序到无序是不可逆过程。例如你整天洗纸牌,也不可能有一天发现是一顺的了。墨水滴到水盆里会逐渐扩散,如果你搅动则会加速扩散,再也没有机会聚成一滴了。
               “序列数交换法”的物理模型可以是这样的。将有规律的数组,例如载体可以是大小一样颜色不同的小球,不同颜色代表不同的元素,放到一个滚筒里,滚动均匀,然后一个个拿出来排列,就得到了新次序下的随机数组。
               现在我们用计算机来模拟这个过程。以ASCII码组成的数组为例(这在计算机是最基础的,以字节为单位), 我们的元素是 0 ~ 255 的数字,共有 256个。
               例如造一个有2560个元素的随机数列:
                             1) 先做一个数值由零到255的循环数列,长度为2560(现在数组周期为256),
                             2) 随机抽取两的序号使它们的数值交换,
                             3) 使 2)进行足够多次,检测其效果,直到满意为止。
下面用 C++语言来实现。只写出关键部分。

#define NN 2560                                             //数组长度
unsigned int i;
unsigned char *str;                                         //定义数组指针
unsigned char ch;
unsigned int n1=0;
 str = new unsigned char[NN+1];                //借用内存
               for(i=0;i<NN;i++) str[i]=i%256;      //形成序列数组
               srand(GetTickCount());                  //用运行时间做随机种子
                for(i=0;i<NN;i++)
                {
                 n1=(rand()+i)%NN;                       //随机生成序号以便交换
                             if(n1==i) goto xia;               //序号相同不处理
                               else 
                               {
                               ch=str[n1];                        //数值交换
                               str[n1]=str[i];
                               str[i]=ch;
                               }
xia: ;  
                }
              delete [] str;                                      //退还内存
        以上程序,借助一个随机函数 rand() 来完成挑选交换目标序号的工作,rand() 实际也对应序号从0到NN-1的数组,只不过表现形式比较怪异,我们称此数组为“捡选数组”。此段程序将有序的数组str[]从头到尾处理了一遍。形象的说就是处理了一次或搅动了一次。如果选择的随机函数比较优秀,一次搅动,可以使数组具有随机数组的统计特性,如果用几个好的随机函数,多做几次可能效果更好。如果随机函数不好,多次也能达到目的。
        试验证明随机函数在这里不是必需的。用开始形成的序列数组str[]取代rand()作为“捡选数组”,以后每次用上次生成的str[]数组作为“捡选数组”,这样经过许多遍处理后也可以形成真随机数组,过程比较缓慢,是个逐渐打乱次序的过程,可以观察到随着搅动次数的增加从序号小的地方开始逐步由规律排列到不规律排列,变成乱码后,又由有周期的乱码向无周期变化。这种自我激励的变化也从一个侧面印证了“熵增加原理”,说明不管用什么方法有序到无序是不可逆转的。但是使用随机函数可以大大加快进程,尤其是好的随机函数,差一些的效率要降低。随机函数只是个工具,真正起作用的是“熵增加原理”。上述正反馈式的自我激励处理过程,简称自激处理,还有其它用途,当借助随机函数的搅动进行到一定程度时,用此方式来扫尾,可以消除随机函数本身处理的痕迹,并可源源不断的产生新的真随机数组。
        如何检测随机数质量。这里是根据随机数组的统计特性来检验它。方法众多仅举一例:
 unsigned int n2=0;
  for(i=0;i<NN;i++)
  {
  if(str[i]==(i%256)) n2++;
  }
               我们知道,元素在特定的位置有 256种可能,所以某元素出现的概率是1/256,元素总数2560乘1/256等于10,当n2接近10时即可,就是再继续搅动,n2将在10 附近震荡,说明均匀度已经饱和。对于真随机数组来说,再多搅性质是不会改变的,只是做无用功罢了。
              真随机数组的一大特点是不能重复出现,现在如何保证呢。因为 1)使用了以时间为种子的随机函数,2)过程结束是靠判断自动完成的。由于系统是多任务系统,同样的运算需要的时间是不同的,这和计算机状态相关,而运行时间又和随机函数种子的数值相关,微小的差异就可以使结果不同,自动完成则搅动的次数就是不确定的,所以完成随机数组的建造过程是不可复现的。
              真随机数组虽然用处很大,但是对普通加密真随机数并不一定便于应用,还是自己控制随机函数种子好些,只要你加入些不确定因素即可,你可以使用密码来控制种子的数值,而密码是运行后输入的,根本不出现在没有运行的程序里,这样对你来说数组是伪随机数组,而这个数组跟搅动的随机函数没有直接关系,但在破解者那里就是真随机数组了,这样的随机数组可以称为单向真随机数组吧,也是做不出来的。


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 好的,以下是使用冒泡排序算对随机十个整数进行升序排序的示例代码(使用 Python 语言实现): ```python import random # 生成随机整数数组 arr = [random.randint(1, 100) for i in range(10)] print("原始数组:", arr) # 冒泡排序 for i in range(len(arr)): for j in range(len(arr)-i-1): if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] print("排序后的数组:", arr) ``` 运行以上代码,将输出类似如下的结果: ``` 原始数组: [4, 94, 24, 67, 47, 35, 27, 80, 34, 68] 排序后的数组: [4, 24, 27, 34, 35, 47, 67, 68, 80, 94] ``` 这里使用了 `random` 模块来生成随机整数数组,其中 `random.randint(1, 100)` 表示生成一个范围在 1 到 100 之间的整数。然后使用两层循环来实现冒泡排序,外层循环控制排序次数,内层循环进行相邻元素之间的比较和交换。最后输出排序后的结果。 ### 回答2: 冒泡排序是一种基本的排序算,其原理是通过相邻元素的比较和交换,将最大的元素逐步“冒泡”到数组的末尾。以下是使用冒泡排序对随机十个整数进行升序排序的步骤: 1. 随机生成十个整数,并将它们存储在一个数组中。 2. 设定一个变量flag,用于标记当前一轮是否进行了元素交换。初始值为false。 3. 从数组的第一个元素开始,依次比较相邻的两个元素,如果前一个元素大于后一个元素,则交换它们的位置。 4. 继续遍历数组,重复执行步骤3,直到遍历到数组的倒数第二个元素。 5. 完成一轮的遍历后,判断flag的值。如果flag为false,表示该轮没有进行任何元素交换,说明数组已经有序,排序完成。如果flag为true,表示该轮进行了元素交换,说明数组还未完全有序,需要继续下一轮的遍历。 6. 如果还未完成排序,重复步骤3至步骤5,直到数组完全有序。 7. 最终得到的数组即为升序排列的结果。 使用冒泡排序对随机十个整数进行升序排序的时间复杂度为O(n^2),其中n为数组的长度。尽管冒泡排序的效率较低,但对于小规模的数组排序是一个简单而直观的选择。 ### 回答3: 冒泡排序算是一种基础的排序算,其核心思想是通过不断比较相邻的元素,将较大的元素逐渐移动到序列的末尾,从而实现升序排序。 假设我们有十个随机整数,为了进行冒泡排序,首先我们要进行n-1次遍历(这里n为数组长度),每次遍历时都将最大的元素移动到最后。具体的步骤如下: 1. 从第一个元素开始,比较它与下一个元素的大小,如果当前元素较大,则交换位置,将较大元素放在后面。 2. 继续比较下一个元素与其后面的元素,重复第一步的操作,直到将最大的元素移动到倒数第二个位置。 3. 重复上述步骤,每次遍历都将最大的元素移动到前一个未排序的位置。 4. 最后,当所有的元素都排好序时,冒泡排序完成。 以下是一个简单的冒泡排序的示例: 随机整数数组:[5, 7, 1, 9, 3, 2, 6, 4, 8, 10] 第一次遍历:[5, 1, 7, 3, 2, 6, 4, 8, 9, 10] 第二次遍历:[1, 5, 3, 2, 6, 4, 7, 8, 9, 10] 第三次遍历:[1, 3, 2, 5, 4, 6, 7, 8, 9, 10] 第四次遍历:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 经过四次遍历后,我们得到了升序排序的结果。 冒泡排序是一种简单但效率较低的排序算,在处理大量数据时可能会变得很慢。在实际应用中,更常使用更为高效的排序算,如快速排序、归并排序等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值