一 说起随机函数,恐怕又有人说这是老生长谈了……一般很多人都形成了自己的固定格式,因为随机数用处比较大,用的时候比较多,拿过来就用了。但是新手不这么 干,他们总是抱有疑惑,我就是一个新手,而且较菜……为了让跟我一样的菜鸟看明白,我会尽量的说得让高手们不屑一顾(:由于可能内容太多可能会分篇,大家 见谅^

计算机的好处是精确,所以它不擅长模拟信号,但它的缺点也是 如此。于是在一些模拟问题上计算机遇到麻烦了……比如所随机数,因为函数嘛,总会是确定的,确定的算法就会生成确定的结果。各种编程语言返回的随机数(确 切地说是伪随机数)实际上都是根据递推公式计算的一组数值,当序列足够长,这组数值近似满足均匀分布。c的标准函数库提供一随机数生成器rand(定义在 stdlib.h),能返回0-RAND_MAX之间均匀分布的伪随机整数(RAND_MAX至少为32767,一般都默认为32767)。

例如:

#include#includevoid main(){       for(int i=0;i<10;i+)             printf("%d\n",rand());}

果我们是第一次运行,而且对其不太清楚,那么它生成的基本上算是0-RAND_MAX之间的等概率随机数列了。但是如果你第二次运行的时候会发现输出结果

仍和第一次一样。:(原来rand()生成伪随机数时需要一个种子(计算伪随机序列的初始数值)才行,如果种子相同就会得到相同的序列结果(这就是函数的

好处T-T)。这个“优点”被有的软件利用于加密和解密。加密时,可以用某个种子数生成一个伪随机序列并对数据进行处理;解密时,再利用种子数生成一个伪

随机序列并对加密数据进行还原。这样,对于不知道种子数的人要想解密就需要多费些事了。当然,这种完全相同的序列对于你来说是非常糟糕的。要解决这个问

题,需要在每次产生随机序列前,先指定不同的种子,这样计算出来的随机序列就不会完全相同了。

srand()

用来设置rand()产生随机数时的随机数种子。在调用rand()函数产生随机数前,必须先利用srand()设好随机数种子(seed),

如果未设随机数种子,

rand()在调用时会自动设随机数种子为1(有人说默认是0,困惑中)。上面的两个例子就是因为没有设置随机数种子,每次随机数种子都自动设成相同值1

,进而导致rand()所产生的随机数值都一样。(可能有人知道C语言中的随机函数random,可是random函数并不是ANSI

C标准,所以说,random函数不能在gcc,vc等编译器下编译通过。我们可以自己编一个^0^)我们需要使程序每一次使用的种子都不一样,现在主要

问题是种子srand的选择是不是接近随机(不存在完全随机),你也可以人为指定种子数。Windows

9x/NT的游戏FreeCell就允许用户指定种子数,这样用户如果一次游戏没有成功,下次还可以以同样的发牌结果再玩一次。但我们还是喜欢系统自动生

成……最简单的方法就是利用系统时间了(几乎所有的人都这么做),因为时间的数值随时间变化而变化,运行两次,一般不会出现前一次和后一次相同的局

面,time(NULL)会返回一个表示当前系统时间的整数(它在time.h中,据说time()函数求出来的是自1970年1月1日到现在的秒数,有

的说是unix元年,不知道这两个是不是一天……:( ,另外有的嫌麻烦会写作time(0))。我们这么来写:

#include#include#include

void main(){

srand((int)time(0));     for(int x=0;x<10;x++)           printf("%d\n",(rand());}

据说如果软件一直开两天,种子会有1/(60*60*24)个可能会重复,虽说这对于一般人已经绝对足够了,但纵然人不舒服,于是我在网上开到有这么写的:

#include#include#include#include

void main(void){    int i;    unsigned int seedVal;    struct timeb timeBuf;    ftime(&timeBuf);    seedVal=((((unsigned int)timeBuf.time&0xFFFF)+                 (unsigned int)timeBuf.millitm)^                 (unsigned int)timeBuf.millitm);    srand((unsigned int)seedVal);    for(i=0;i<10;++i)        printf("%6d\n",rand());}

(下面是关于它的解释,但我也不是太明白,引用过来大家分析一下)

上面的程序先是调用_ftime()来检查当前时间,并把它的值存入结构成员timeBuf.time中,当前时间的值从1970年1月1日开始以秒计

算。在调用了_ftime()之后,在结构timeBuf的成员millitm中还存入了当前那一秒已经度过的毫秒数,但在DOS中这个数字实际上是以百

分之一秒来计算的。然后,把毫秒数和秒数相加,再和毫秒数进行异或运算。当然也可以对这两个结构成员进行更多的计算,以控制seedVal的取值范围,并

进一步加强它的随机性,但上例用的逻辑运算就已经足够了。”

看下面代码:

void main() {  for(int i=0;i<100000;i++)  {  srand( (unsigned)time( NULL ) );  printf("%d\n",rand()); } }

什么总是生成一个数???因为此程序产生一个随机数之前,都调用一次srand,而由于计算机运行很快,所以每用time得到的时间都是一样的(time

的时间精度较低,只有55ms)。这样相当于使用同一个种子产生随机序列,所以产生的随机数总是相同的。把srand放在循环外看看: srand( (unsigned)time( NULL ) ); for(int i=0;i<100000;i++) 问题解决了:)

然生成的是

0-RAND_MAX之间均匀分布的随机整数(我们姑且把以上方法生成的是理想的随机数吧),那么要生成0-x之间(包括0不包括x)的随机数就把

rand()改成  rand()/(double)RAND_MAX*x ,要生成x-y之间(包括x不包括y)的就是

rand()/(double)RAND_MAX*(y-x)+x   了。但是如果要生0-10之间的整数很多人会这么写:

#include#include#include

void main(){

srand((int)time(0));     for(int x=0;x<10;x++)           printf("%d\n",(rand()%10);}

x-y的就是 rand()%(y-x)+x

???

懂一点概率的就知道这样写,会使得到的数列分布不均的,但是大家确实都喜欢这么写……因为在x的值比较小,RAND_MAX相对较大,而生成的数列有不算

太大,又是用来解决精确度要求不高的问题(如一些游戏目标,传说游戏中踩地雷式的遇敌就是用rand()实现的.

当主角在地图上走的时候动不动冒出三两小兵挑衅兼找死.它的实现方式是设主角所立位置为0,主角每走一步,变量加1,当变量==随机取得的数时,小兵出

现),这样写足够了……

下面再讨论生成m个小于n的不重复随机数的算法

本人认为算法结构很重要,但语句结构也很重要,所以我喜欢一个算法给出多个语句结构……

最容易想到的傻瓜算法,逐个产生这些随机数,每产生一个,都跟前面的随机数比较,如果重复,就重新产生:

算法一(1)

srand((unsigned)time(NULL));

for(j = 0; j < m; j++) {

a:a[j] = rand() % n; for(i=0;i

早的时候学编程都喜欢用goto语句,因为过去算法是用流程图表示的,用goto可以直接转译,而且循环语句发展不完善,仅仅是作为条件分支的一个补充,

如果条件分支箭头向上就是一个循环,而且goto可以实现过去循环所不能实现的结构,形成很巧妙的循环交叉。所以过去一般认为有两种结构,顺序和分支,循

环是分支的特殊情况。但是break和continue语句使这些结构实现成为可能,后来发现goto的使用会造成维护和调试的许多麻烦,所以循环逐渐代

替了goto,使程序更有层次。现在编程不建议用goto了,如果用goto还会被认为编程修养不好……言归正题,把它的goto去掉:

算法一(2)

srand((unsigned)time(NULL));

j=0; while (j

j++}

但是后来都建议用for循环,这样可以使循环条件跟紧凑:

算法一(3)

srand((unsigned)time(NULL));

for(j=0;j

{a[j]=rand()%n;

for(i=0;i

{if(a[i]==a[j])

{i=-1;a[j]=rand()%n;}

}

}

但这是个很笨的方法,且比较次数呈线性增长,越往后次数越多……另一个想法是生成一个就把它从中去掉,就可以实现不重复了:

算法二(1)

for (i=0;i

a[i]=i+1;

for(i=0;i

{j=rand()%(n-i);

b[i]=a[j];

for (k=j;k

a[k]=a[k+1];

}

b[]是生成的随机数列

这样做也太麻烦了,生成的直接做个标记不就行了?

算法三(1-1)

i=rand()%m;

a[i]=1;b[0]=i;

for(j=1;j

{for (i=rand()%m;a[i]==1;i=rand()%m);

b[j]=i;a[i]=1;

}

写紧凑一些吧,直接:

算法三(1-2)

for(j=0;j

{for (i=rand()%m;a[i]==1;i=rand()%m);

b[j]=i;a[i]=1;

}

但是我看到了更简洁的:

int n=某值;

int a[n]={0};

for (i=1;i<=n;i++)

{while(a[x=rand()%n]);

a[x]=i;

}

这个无循环体的while保证a[m]是初始化的0状态。这生成了n个,我们只取m个,这太浪费了,结合一下:

int n=某值,m=某值;

int a[n]={0},b[m]

for (i=1;i<=n;i++)

{while(a[x=rand()%n]);

b[i]=x;a[x]=1;

}

但是总叫人不舒服,对这种算法谁有更好的写法呢?

这种算法越到后面,遇到已使用过的元素的可能性越高,重复次数就越多,但是当m较小时还是很好的:)

这都不太让人满意么?看看下面这个:

算法四(1)

for (i=0;i

a[i]=i+1;

for (i=n-1;i>0;i--)

{w=rand()%i;

t=a[i];

a[i]=a[w];

a[w]=t;

}

这个算法很不错,有人会怀疑其随机性,但个人认为是没问题的,首先第二行按顺序用0到n填满整个数组;第三行,是随机产生从0到n-2个数组下标,把这个下标的元素值跟n-1下标的元素值交换,一直进行到下标为1的元素。因此它只需要遍历一次就能产生全部的随机数。

但这样会生成n个小于n的随机数,我们只要m个,再加两句:

for(i=0;i

b[i]=a[i];

b[]是生成的随机数列

如果m和n很接近的话或者相等是最好,但可能不是……那改一下:

算法四(2)

for (i=0;i

a[i]=i+1;

for (i=0;i

{w=rand()%n;

t=a[i];

a[i]=a[w];

a[w]=t;

}

但是条件反过来了,如果m远小于n还行,如果接近,其随机性就存在问题了(为什么?),再改一下:

算法四(3)

for (i=0;i

a[i]=i+1;

for (i=0;i

{w=rand()%(n-i)+i;

t=a[i];

a[i]=a[w];

a[w]=t;

}

这样可以万无一失了……

c语言连续生成不同随机数_【转】关于C语言生成不重复的随机数相关推荐

  1. c语言连续生成不同随机数_C语言随机数生成教程,C语言rand和srand用法详解

    在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌. 在C语言中,我们一般使用 头文件中的 rand() 函数来生成随机数,它的用法为: int ran ...

  2. C语言生成不重复的随机数数组

    C语言生成不重复的随机数数组 //一个随机数数组生成算法,生成0-n不重复的随机数数组 //本例子使用的是0-99的范围,参数可改 //如果是在最后面的数组,使用完,丢弃 //如果是前面的数则用后面不 ...

  3. python随机生成英文字符串_如何用Python语言生成随机字符串 | 学步园

    这是在Stackoverflow的关于 "用Python语言简洁地生成随机字符串" 的经典问答. 将此文翻译并分享下. 我想生成一个长度为N的字符串. 这个字符串应由数字和大写英文 ...

  4. 【C语言】连续生成多个随机数

    C语言连续生成多个随机数 在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌. 在C语言中,我们一般使用 <stdlib.h> 头文件中的 ...

  5. C语言生成n个随机坐标,c语言如何生成随机数 怎样用c语言生成n个随机数?

    C语言中如何产生很大的随机数?这个可以一个一个的来生成啊,每次生成一个0-9之前的随机数,然后生成几次 组合起来就可以了. C语言 如何连续产生随机数? 如果我想用C在1s的时间内连续产生多个随机数, ...

  6. java高斯分布随机数_生成符合高斯分布或者其他任意分布的随机数

    在一些情况下经常需要用到随机数,而高斯随机数又是最常用到的.这一篇讲一下如何编程生成符合正态分布的高斯随机数,甚至任何其他分布的随机数. 我们知道C语言的标准库函数可以生成符合均匀分布的伪随机数.那么 ...

  7. c语言rand生成1 100随机数,c语言生成1~100随机数

    C语言如何srand和rand函数产生10个1-100内的随机数 10个是任意的,也可能是100个,1-100也是任意的...CSS布局HTML小编今天和大家分享解,详细的有追加 需要准备的材料分别有 ...

  8. 获取连续生成的100-200范围的随机数,直到生成的随机数与前一个随机数相等,停止运行

    编写程序,获取连续生成的100-200范围的随机数,直到生成的随机数与前一个随机数相等,停止运行 题目:编写程序,获取连续生成的100-200范围的随机数,直到生成的随机数与前一个随机数相等,停止运行 ...

  9. C语言:生成随机数(并非固定的随机数)——rand()、srand()

    C语言:生成随机数 1.rand() 函数 2.srand() 函数 3.生成一定范围内的随机数 在实际编程中,我们经常需要生成随机数. 1.rand() 函数 在C语言中,我们一般使用 <st ...

  10. c语言随机产生100个字母,C语言实现生成1到100随机数的方法

    C语言实现生成1到100随机数的方法 发布时间:2020-06-29 14:08:59 来源:亿速云 阅读:7054 作者:Leah 本篇文章为大家展示了C语言实现生成1到100随机数的方法,代码简明 ...

最新文章

  1. 安装php ssh2扩展
  2. 列索引对SharePoint大列表性能的影响
  3. 线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel
  4. 【译】索引进阶(四):页和区
  5. java 字母金字塔_LeetCode756:金字塔转换矩阵(JAVA题解)
  6. Ⅴ0还有别的方法设置图案吗_水冷空调扇如何使用 水冷空调扇使用方法介绍【图文】...
  7. SpringCloud使用Prometheus监控(基于Eureka)
  8. 一个可以在Linux环境下找到,杀死,并重启Tomcat的脚本
  9. Java第二次作业參考代码
  10. 【狂神说Redis】3五大数据类型
  11. 精灵五笔 优化指南【原】
  12. ThinkPHP 商城属性添加
  13. 二级计算机excel以宏保存,excel宏保存 设置宏保存位置的操作方法
  14. 关于使用VBA调用AutoCAD的学习
  15. 计算机是如何工作的?
  16. 在Qt中配置海康工业相机SDK及遇到的问题(报错)
  17. Ubuntu 20.04 : 几个BT下载软件和命令
  18. DIY:制作一个语音识别的空调遥控器
  19. 用 python 快速「卡通化」人物头像
  20. U盘安装ubuntu 16.04 遇到 gfxboot.c32:not a COM32R image boot 的解决方法

热门文章

  1. android+数据库类型转换,ANDROID数据库错误:不兼容的类型:INT不能转换到CursorFactory...
  2. 2020年到2021年计算机技术,2020年读计算机技术专业好不好
  3. echarts无数据时显示无数据_无服务器数据库竞技,哪家云服务落伍了?
  4. C++自定义sort排序
  5. java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException
  6. HDU 6188:Duizi and Shunzi(贪心)(广西邀请赛)
  7. 基础图像处理之混合空间增强——(Java:拉普拉斯锐化、Sobel边缘检测、均值滤波、伽马变换)...
  8. HDU 5265 pog loves szh II (二分查找)
  9. OpenLayers3基础教程——OL3 介绍interaction
  10. C#|GMap.NET控件基本使用-高德地图