vc下产生一个四位随机不重复数字
- 格式:docx
- 大小:82.60 KB
- 文档页数:2
(c/c++程序设计课程设计)设计说明书猜数字游戏的设计与实现学生姓名刘帆学号0918014003班级计本091班成绩指导教师曹阳计算机科学与技术系2010年 07 月09 日c/c++程序设计课程设评阅书课程设计任务书2009 —2010 学年第二学期专业:计算机科学与技术学号: 0918014003 姓名:刘帆课程设计名称: c\c++程序设计课程设计设计题目:猜数字游戏的设计与实现完成期限:自 2010 年 6 月 28 日至 2010 年 7 月 9 日共 2 周设计依据、要求及主要内容(可另加附页):猜数字是一种益智类小游戏,游戏规则比较简单,一般两个人玩,一方出数字,一方猜。
用C/C++语言编写一个程序实现《猜数字》游戏中的出数字方,要求程序完成以下功能:1)阐述设计思想,画出流程图;2)随机抽取一个4位整数K,要求这个四位数没有重复数字,最高位不是0;3)提示玩家,猜一个数字;4)根据玩家猜的数,与K比较,判断玩家猜的数字中位置正确的数字个数m和数字正确而位置不对的数的个数n,并以mAnB的形式输出;5)如果玩家没有猜对,那么提示mAnB,让玩家继续猜,否则输出“你棒极了,这个数字就是……,你一共猜了……次哦!”;6)如果玩家猜了X(X<M,M为猜数的最多次数)次还不对,那么提示玩家“你已经猜了x次了,还要继续吗?请选择;如果X=M,则给玩家提示相应的信息;7)说明测试方法,写出完整的运行结果,较好的界面设计,编写课程设计报告。
指导教师(签字):教研室主任(签字):批准日期:年月日摘要猜数字是一种益智类小游戏,游戏规则比较简单,一般两个人玩,一方出数字,一方猜,出数字是由随机函数产生一个数字不重复的四位数(最高位不为零)。
本文以VC++作为软件开发环境,设计并实现了猜数字游戏软件。
该软件界面美观,操作简单,并根据所猜的数字给出相应的结果或提示。
关键词:猜数字;VC++;随机函数目录1 课题描述 (5)2 问题分析和任务定义 (6)3逻辑设计 (7)4 详细设计 (9)5 程序编码 (13)6 程序调试与测试 (18)7 结果分析 (21)8 总结 (22)参考文献 (23)1课题描述本次课题是猜数字游戏的设计与实现。
c语言随机生成8位数字在计算机编程领域,随机数生成是一项非常重要的技术。
C语言作为一种广泛应用的编程语言,也提供了生成随机数的函数库。
本文将介绍如何使用C语言生成8位数字的随机数。
在C语言中,我们可以使用rand()函数来生成随机数。
该函数位于stdlib.h头文件中,可以生成一个范围在0到RAND_MAX之间的随机整数。
但是,直接使用rand()函数生成的随机数可能不满足我们的需求,因为它的范围太大了。
为了生成8位数字的随机数,我们需要对rand()函数生成的随机数进行处理。
具体的处理方法如下:1. 使用srand()函数设置随机数种子。
srand()函数也位于stdlib.h头文件中,它用于设置随机数生成器的种子。
我们可以使用time()函数获取当前时间作为种子,确保每次运行程序时生成的随机数都不同。
2. 使用rand()函数生成一个0到99999999之间的随机整数。
我们可以通过对生成的随机数取模100000000来限制其范围。
3. 如果生成的随机数小于10000000,我们可以通过加上10000000来保证生成的随机数一定是8位数字。
下面是一个使用C语言生成8位数字随机数的示例代码:```c#include <stdio.h>#include <stdlib.h>#include <time.h>int main() {int random_num;srand(time(NULL)); // 设置随机数种子random_num = rand() % 100000000; // 生成0到99999999之间的随机整数if (random_num < 10000000) {random_num += 10000000; // 保证生成的随机数是8位数字}printf("随机生成的8位数字为:%d\n", random_num);return 0;}```通过运行上述代码,我们可以在控制台上看到一个随机生成的8位数字。
1-0:Microsoft VC++产生随机数的原理:Srand ( )和Rand( )函数。
它本质上是利用线性同余法,y=ax+b(mod m)。
其中a,b,m都是常数。
因此rand的产生决定于x,x被称为Seed。
Seed需要程序中设定,一般情况下取系统时间作为种子。
它产生的随机数之间的相关性很小,取值范围是0—32767〔int〕,即双字节〔16位数〕,假设用unsigned int 双字节是65535,四字节是4294967295,一般可以满足要求。
1-1:线性同余法:其中M是模数,A是乘数,C是增量,为初始值,当C=0时,称此算法为乘同余法;假设C≠0,那么称算法为混合同余法,当C取不为零的适当数值时,有一些优点,但优点并不突出,故常取C=0。
模M大小是发生器周期长短的主要标志,常见有M为素数,取A为M 的原根,那么周期T=M-1。
例如:a=1220703125a=32719 〔程序中用此组数〕a=16807代码:void main( ){const int n=100;double a=32719,m=1,f[n+1],g[n],seed;m=pow(2,31);cout<<"设置m值为"<<m-1<<endl;cout<<"输入种子"<<endl; //输入种子cin>>seed;f[0]=seed;for(int i=1;i<=n;i++) //线性同余法生成随机数{f[i]=fmod((a*f[i-1]),(m-1));g[i-1]=f[i]/(m-1);cout.setf(ios::fixed);cout.precision(6); //设置输出精度cout<<i<<" "<<'\t'<<g[i-1]<<endl;}}1-2:人字映射递推公式就是有名的混沌映射中的“人字映射〞或称“帐篷映射〞,它的非周期轨道点的分布密度函数:人字映射与线性同余法结合,可产生统计性质优良的均匀随机数。
电气信息学院实训报告课程名称: 软件项目实训实训题目: 猜数字游戏年级/专业/班: 2009过程自动化01 学生姓名: 学号: 实训成绩:指导教师签名:年月日1.引言1.1系统概述猜数字是一种益智类小游戏,游戏规则比较简单,一般两个人玩,一方出数字,一方猜。
要求用vc++6.0中mfc编写一个程序实现猜数字游戏中的出数字方,实现数字之间的相互比较,让玩家找出电脑写的三位数字,而玩家在找出三位数字中,电脑需要给出玩家一些提示信息,用以帮助玩家找出答案。
对于猜一个各个位数不等的三位数字,电脑需要在程序刚运行时,确定一个随机的三位数,且各个位数不相等。
而在玩家输入数字时,也需要检验玩家输入的数字是否满足条件,即一个各个位数不重复的三位数。
只有玩家输入正确的数字后,电脑才能进行比较数字的运算,如果玩家输入的数字和电脑的不相等,输出提示信息,并应重新读取玩家的数字进行判断,直到玩家放弃猜数字或数字猜对为止。
玩游戏者通过游戏提示输入八次来匹配上面所输入的数字。
a表示位置正确且数字正确,b表示数字正确而位置不正确。
首先,由设计程序随机产生一个三位整数k,要求这个两位数字没有重复数字,且最高位不是0。
然后,玩家可以猜一个三位数字,根据玩家猜的数,与k比较,判断玩家猜的数字是否正确,同时,提示猜的数字中位置正确的数字个数m和数字正确而位置不正确的数的个数n,并以manb的形式输出(a表示位置和数字都正确,b表示数字正确而位置不正确)。
如果玩家猜了9次还不对,那么提示玩家“游戏失败!”。
1.2 需求分析电脑游戏的出现与1960年代电子计算机进入美国大学校园有密切的联系。
当时的环境培养出了一批编程高手。
1962年一位叫斯蒂夫·拉塞尔的大学生在美国dec公司生产的pdp-1型电子计算机上编制的《宇宙战争》(space war)是当时很有名的电脑游戏。
一般认为,他是电脑游戏的发明人。
1970年代,随着电子计算机技术的发展,其成本越来越低。
c随机数生成1到100
生成随机数步骤1:在要输入随机数的单元格中输入=rand()。
生成随机数步骤2:按enter键,就能产生0~1之间的随机数。
分解成随机数步骤3:当我们须要产生其他范围的随机数时,我们可以以rand函数做为基数,制订其他范围的随机数。
假设最轻数为x,最大数为y,随机数=x+rand()*(y-x)。
假设最轻数为30,最大数为60,随机数=30+rand()*(60-30)。
在单元格输出
=30+rand()*(60-30)。
生成随机数步骤4:按enter键,就能产生30~60之间的随机数。
分解成随机数步骤5:当我们须要产生整数时,我们须要使用randbetween函数,随
机数=randbetween(最小值,最大值)。
比如说必须产生1至50的随机整数,随机数
=randbetween(1,50)。
在单元格输出=randbetween(1,50)。
生成随机数步骤6:按enter键,就能产生1~50之间整数的随机数。
分解成随机数步骤7:当然我们可以混合采用,产生我们想的随机数。
比如说我们必
须产生三位小数的随机数。
随机数=randbetween(1,)/。
在单元格输出
=randbetween(1,)/。
生成随机数步骤8:按enter键,就能产生0,.~2之间三位小数的随机数。
3.excel 随机数字公式的采用教程
4.excel怎么使用randbetween随机数函数
5.excel怎么采用议和类函数
7.随机数函数randbetween在excel中的使用。
随机产⽣四位,任意位或者范围数字⽅法⼀、⽤Math包中⽅法实现1.随机产⽣四位数[1000,9999]num=(int)(Math.random()*9000)+1000;Math.random()⽅法是产⽣double型[0,1)的数据,[0,1)*9000=[1,9001),⽤int类型强转后便是[0,8999], 因⽽可以得到1000~9999的四位随机数。
**PS:解释下double类型强转int类型,会导致double数据⼩数部分丢失Eg:double a=3.14529;int b=(int)a;b=3**2.随机产⽣规定范围内数字Eg:[1000,9999)num=(int)(Math.random()*8999)+1000;4.随机产⽣规定范围内数字Eg:(1000,9999]num=(int)(Math.random()*8999)+1000+1;5.随机产⽣规定范围内数字(1000,9999)num=(int)(Math.random()*8998)+1000+1;下⾯个⼈总结,⽤到的范围可能存在局限/*随机产⽣规定范围内数字[15,36]规律:num=(int)(Math.random()*(y-x+1))+x;*/num=(int)(Math.random()*22)+15;/*随机产⽣规定范围内数字(15,36)既[16,35]规律:num=(int)(Math.random()*(y-x-1))+x+1;*/num=(int)(Math.random()*20)+16;/*随机产⽣规定范围内数字[15,36)既[15,35]规律:num=(int)(Math.random()*(y-x))+x;*/num=(int)(Math.random()*21)+15;/*随机产⽣规定范围内数字(15,36]既[14,36]规律:num=(int)(Math.random()*(y-x+2))+x+1;*/num=(int)(Math.random()*23)+15;⼆、⽤Random类实现Java中提供了java.util.Random类,可以通过实例化⼀个Random对象创建⼀个随机数⽣成器,Random r=new Random();package method3;import java.util.Random;public class RandomDemo {public static void main(String[] args) {// TODO ⾃动⽣成的⽅法存根Random r = new Random();System.out.println(r.nextInt()); // 随机产⽣⼀个整数System.out.println(r.nextInt(10)); // 随机产⽣0到10(不包括10)范围内的⼀个整数System.out.println(r.nextDouble());// 随机产⽣⼀个双精度型值System.out.println(r.nextBoolean());// 随机产⽣⼀个布尔型值System.out.println(r.nextFloat());// 随机产⽣⼀个浮点型值System.out.println(r.nextGaussian());// 随机产⽣⼀个概率为⾼斯分布的双精度型值}}。
C#生成不重复的随机数介绍我们在做能自动生成试卷的考试系统时,常常需要随机生成一组不重复随机数的题目,在.net Framework中提供了一个专门用来产生随机数的类System.Random。
对于随机数,大家都知道,计算机不可能产生完全随机的数字,所谓的随机数发生器都是通过一定的算法对事先选定的随机种子做复杂的运算,用产生的结果来近似的模拟完全随机数,这种随机数被称作伪随机数。
伪随机数是以相同的概率从一组有限的数字中选取的。
所选数字并不具有完全的随机性,但是从实用的角度而言,其随机程度已足够了。
伪随机数的选择是从随机种子开始的,所以为了保证每次得到的伪随机数都足够地“随机”,随机种子的选择就显得非常重要。
如果随机种子一样,那么同一个随机数发生器产生的随机数也会一样。
一般地,我们使用同系统时间有关的参数作为随机种子,这也是.net Framework 中的随机数发生器默认采用的方法。
我们可以使用两种方式初始化一个随机数发生器:第一种方法不指定随机种子,系统自动选取当前时间作为随机种子:Random ro = new Random();第二种方法可以指定一个int型参数作为随机种子:int iSeed=10;Random ro = new Random(10);long tick = DateTime.Now.Ticks;Random ran = new Random((int)(tick & 0xffffffffL) | (int) (tick >> 32));这样可以保证99%不是一样。
之后,我们就可以使用这个Random类的对象来产生随机数,这时候要用到Random.Next()方法。
这个方法使用相当灵活,你甚至可以指定产生的随机数的上下限。
不指定上下限的使用如下:int iResult;iResult=ro.Next();下面的代码指定返回小于100的随机数:int iResult;int iUp=100;iResult=ro.Next(iUp);而下面这段代码则指定返回值必须在50-100的范围之内:int iResult;int iUp=100;int iDown=50;iResult=ro.Next(iDown,iUp);除了Random.Next()方法之外,Random类还提供了Random.NextDouble()方法产生一个范围在0.0-1.0之间的随机的双精度浮点数:double dResult;dResult=ro.NextDouble();但是用Random类生成题号,会出现重复,特别是在数量较小的题目中要生成不重复的的题目是很难的,参考了网上的一些方法,包括两类,一类是通过随机种子入手,使每一次的随机种子不同,来保证不重复;第二类是使用一些数据结构和算法。
python⽣成四位随机数有些时候需要发送短信给⽤户⽣成四位随机数字,这⾥在python中我们可以根据python⾃带的标准库random和string来实现。
random1# random.choice2def choice(self, seq):3"""Choose a random element from a non-empty sequence."""4try:5 i = self._randbelow(len(seq))6except ValueError:7raise IndexError('Cannot choose from an empty sequence') from None8return seq[i]1# random.choices2def choices(self, population, weights=None, *, cum_weights=None, k=1):3"""Return a k sized list of population elements chosen with replacement.45 If the relative weights or cumulative weights are not specified,6 the selections are made with equal probability.78"""9 random = self.random10if cum_weights is None:11if weights is None:12 _int = int13 total = len(population)14return [population[_int(random() * total)] for i in range(k)]15 cum_weights = list(_itertools.accumulate(weights))16elif weights is not None:17raise TypeError('Cannot specify both weights and cumulative weights')18if len(cum_weights) != len(population):19raise ValueError('The number of weights does not match the population')20 bisect = _bisect.bisect21 total = cum_weights[-1]22 hi = len(cum_weights) - 123return [population[bisect(cum_weights, random() * total, 0, hi)]24for i in range(k)]1# random.sample23def sample(self, population, k):4"""Chooses k unique random elements from a population sequence or set.56 Returns a new list containing elements from the population while7 leaving the original population unchanged. The resulting list is8 in selection order so that all sub-slices will also be valid random9 samples. This allows raffle winners (the sample) to be partitioned10 into grand prize and second place winners (the subslices).1112 Members of the population need not be hashable or unique. If the13 population contains repeats, then each occurrence is a possible14 selection in the sample.1516 To choose a sample in a range of integers, use range as an argument.17 This is especially fast and space efficient for sampling from a18 large population: sample(range(10000000), 60)19"""2021# Sampling without replacement entails tracking either potential22# selections (the pool) in a list or previous selections in a set.2324# When the number of selections is small compared to the25# population, then tracking selections is efficient, requiring26# only a small set and an occasional reselection. For27# a larger number of selections, the pool tracking method is28# preferred since the list takes less space than the29# set and it doesn't suffer from frequent reselections.3031if isinstance(population, _Set):32 population = tuple(population)33if not isinstance(population, _Sequence):34raise TypeError("Population must be a sequence or set. For dicts, use list(d).")35 randbelow = self._randbelow36 n = len(population)37if not 0 <= k <= n:38raise ValueError("Sample larger than population or is negative")39 result = [None] * k40 setsize = 21 # size of a small set minus size of an empty list41if k > 5:42 setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets43if n <= setsize:44# An n-length list is smaller than a k-length set45 pool = list(population)46for i in range(k): # invariant: non-selected at [0,n-i)47 j = randbelow(n-i)48 result[i] = pool[j]49 pool[j] = pool[n-i-1] # move non-selected item into vacancy50else:51 selected = set()52 selected_add = selected.add53for i in range(k):54 j = randbelow(n)55while j in selected:56 j = randbelow(n)57 selected_add(j)58 result[i] = population[j]59return result从上⾯这三个函数看来,都可以在给定的⼀个数字集内随机产⽣四位数字。
JAVA随机数之多种方法从给定范围内随机N个不重复数在Java中,我们可以使用多种方法从给定范围内随机生成N个不重复的数。
下面将详细介绍三种常用的方法:使用集合、Fisher-Yates洗牌算法和递归。
1.使用集合:使用集合可以保证生成的数不重复。
我们可以使用Java中的HashSet类来完成这个任务。
算法如下:(1)创建一个HashSet对象来存储生成的数。
(2)生成一个随机数,并检查是否在HashSet中已经存在。
(3)如果不存在,将随机数添加到HashSet中,并继续生成下一个随机数,直到HashSet中的元素个数达到N。
(4)返回HashSet中的元素作为结果。
代码示例:```javaimport java.util.HashSet;import java.util.Random;public class RandomNumberGeneratorpublic static HashSet<Integer> generateRandomNumbers(int min, int max, int count)HashSet<Integer> numbers = new HashSet<>(;Random random = new Random(;while (numbers.size( < count)int randomNumber = random.nextInt(max - min + 1) + min;numbers.add(randomNumber);}return numbers;}public static void main(String[] args)HashSet<Integer> randomNumbers = generateRandomNumbers(1, 10, 5);System.out.println(randomNumbers);}}```该代码可以生成1到10之间的5个不重复的随机数。
随机数的产生摘要本文研究了连续型随机数列的产生,先给出了均匀分布的随机数的产生算法,在通过均匀分布的随机数变换得到其他连续型随机数的产生算法.在vc 环境下,我们给出了产生均匀分布随机数的算法,然后探讨了同余法的理论原理.通过均匀随机数产生其他分布的随机数,我们列举了几种通用算法,并讨论各个算法的优缺点,最后以正态分布为例验证高效舍选法的优势. 正文一、 随机数与伪随机数随机变量η的抽样序列12,,n ηηη ,…称为随机数列.如果随机变量η是均匀分布的,则η的抽样序列12,,n ηηη ,…称为均匀随机数列;如果随机变量η是正态分布的随机变量则称其抽样序列为正态随机数列.比如在掷一枚骰子的随机试验中出现的点数x 是一个随机变量,该随机变量就服从离散型均匀分布,x 取值为1,2,3,4,5,6,取每个数的概率相等均为1/6.如何得到x 的随机数?通过重复进行掷骰子的试验得到的一组观测结果12,,,n x x x 就是x 的随机数.要产生取值为0,1,2,…,9的离散型均匀分布的随机数,通常的操作方法是把10个完全相同的乒乓球分别标上0,1,2,…,9,然后放在一个不透明的袋中,搅拦均匀后从中摸出一球记号码1x 后放回袋中,接着仍将袋中的球搅拌均匀后从袋中再摸出一球记下号码2x 后再放回袋中,依次下去,就得到随机序列12,,,n x x x .通常称类似这种摸球的方法产生的随机数为真正的随机数.但是,当我们需要大量的随机数时,这种实际操作方法需要花费大量的时间,通常不能满足模拟试验的需要,比如教师不可能在课堂上做10000次掷硬币的试验,来观察出现正面的频率.计算机可以帮助人们在很短时间产生大量的随机数以满足模拟的需要,那么计算机产生的随机数是用类似摸球方法产生的吗?不是.计算机是用某种数学方法产生的随机数,实际上是按照一定的计算方法得到的一串数,它们具有类似随机数的性质,但是它们是依照确定算法产生的,便不可能是真正的随机数,所以称计算机产生的随机数为伪随机数.在模拟计算中通常使用伪随机数.对这些伪随机数,只要通过统计检验符合一些统计要求,如均匀性、随机性等,就可以作为真正的随机数来使用,我们将称这样产生的伪随机数为随机数.在计算机上用数学方法产生随机数的一般要求如下:1)产生的随机数列要有均匀性、抽样的随机性、试验的独立性和前后的一致性.2)产生的随机数列要有足够长的周期,以满足模拟实际问题的要求.3)产生随机数的速度要快,占用的内存少.计算机产生随机数的方法内容是丰富的,在这里我们介绍几种方法,计算机通常是先产生[0,1]区间上均匀分布的随机数,然后再产生其他分布的随机数.二、均匀分布随机数的产生2.1 算法1在vc的环境下,为我们提供了库函数rand()来产生一个随机的整数.该随机数是平均在0~RAND_MAX之间平均分布的,RAND_MAX是一个常量,在VC6.0环境下是这样定义的:#define RAND_MAX 0x7fff它是一个short 型数据的最大值,如果要产生一个浮点型的随机数,可以将rand()/1000.0这样就得到一个0~32.767之间平均分布的随机浮点数.如果要使得范围大一点,那么可以通过产生几个随机数的线性组合来实现任意范围内的平均分布的随机数.例如要产生-1000~1000之间的精度为四位小数的平均分布的随机数可以这样来实现.先产生一个0到10000之间的随机整数.方法如下:int a = rand()%10000;然后保留四位小数产生0~1之间的随机小数:double b = (double)a/10000.0;然后通过线性组合就可以实现任意范围内的随机数的产生,要实现-1000~1000内的平均分布的随机数可以这样做:double dValue =(rand()%10000)/10000.0*1000-(rand()%10000)/10000.0*1000;则dValue就是所要的值.但是,上面的式子化简后就变为:double dValue = (rand()%10000)/10.0-(rand()%10000)/10.0;这样一来,产生的随机数范围是正确的,但是精度不正确了,变成了只有一位正确的小数的随机数了,后面三位的小数都是零,显然不是我们要求的,什么原因呢,又怎么办呢.先找原因,rand()产生的随机数分辨率为32767,两个就是65534,而经过求余后分辨度还要减小为10000,两个就是20000而要求的分辨率为1000*10000*2=20000000,显然远远不够.下面提供的方法可以实现正确的结果:double a = (rand()%10000) * (rand()%1000)/10000.0;double b = (rand()%10000) * (rand()%1000)/10000.0;double dValue = a-b;则dValue就是所要求的结果.在下面的函数中可以实现产生一个在一个区间之内的平均分布的随机数,精度是4位小数.double AverageRandom(double min,double max){int minInteger = (int)(min*10000);int maxInteger = (int)(max*10000);int randInteger = rand()*rand();int diffInteger = maxInteger - minInteger;int resultInteger = randInteger % diffInteger + minInteger;return resultInteger/10000.0;}但是有一个值得注意的问题,随机数的产生需要有一个随机的种子,因为用计算机产生的随机数是通过递推的方法得来的,必须有一个初始值,也就是通常所说的随机种子,如果不对随机种子进行初始化,那么计算机有一个缺省的随机种子,这样每次递推的结果就完全相同了,因此需要在每次程序运行时对随机种子进行初始化,在vc中的方法是调用srand(int)这个函数,其参数就是随机种子,但是如果给一个常量,则得到的随机序列就完全相同了,因此可以使用系统的时间来作为随机种子,因为系统时间可以保证它的随机性.调用方法是srand(GetTickCount()),但是又不能在每次调用rand()的时候都用srand(GetTickCount())来初始化,因为现在计算机运行时间比较快,当连续调用rand()时,系统的时间还没有更新,所以得到的随机种子在一段时间内是完全相同的,因此一般只在进行一次大批随机数产生之前进行一次随机种子的初始化.下面的代码产生了400个在-1~1之间的平均分布的随机数. double dValue[400];srand(GetTickCount());for(int i= 0;i < 400; i++){double dValue[i] = AverageRandom(-1,1);}用该方法产生的随机数运行结果如图1所示:图1 400个-1~1之间平均分布的随机数2.2 算法2:用同余法产生随机数同余法简称为LCG(Linear Congruence Gener-ator),它是Lehmer 于1961年提出来的.同余法利用数论中的同余运算原理产生随机数.同余法是目前发展迅速且使用普遍的方法之一.同余法(LCG)递推公式为1()(mod )n n x ax c m -=+ (n=1,2,…), (1) 其中n x ,a ,c 均为正整数.只需给定初值x.,就可以由式(1)得到整数序列{n x },对每一n x ,作变换n u =n x /m ,则{n u }(n=1,2,…)就是[0,1)上的一个序列.如果{n u }通过了统计检验,那么就可以将n u 作为[0,1)上的均匀分布随机数.在式(1)中,若c=0,则称相应的算法为乘同余法,并称口为乘子;若c ≠0,则称相应的算法为混合同余法.同余法也称为同余发生器,其中0x 称为种子.由式(1)可以看出,对于十进制数,当取模m=10k(k 为正整数)时,求其同余式运算较简便.例如36=31236(mod102),只要对21236从右截取k=2位数,即得余数36.同理,对于二进制数,取模m=2k 时,求其同余式运算更简便了.电子计算机通常是以二进制形式表示数的.在整数尾部字长为L 位的二进制计算机上,按式(1)求以m 为模的同余式时,可以利用计算机具有的整数溢出功能.设L 为计算机的整数尾部字长,取模m=2L ,若按式(1)求同余式时,显然有 11111;[()/].n n n n n n n ax c m x ax c ax c m x ax c m ax c m -----+<=++≥=+-+当时,则当时,则这里[x]是取x 的整数部分.在电子计算机上由1n x -求n x 时,可利用整数溢出原理.不进行上面的除法运算.实际上,由于计算机的整数尾部字长为L ,机器中可存放的最大整数为2L -1,而此时a 1n x -+c ≥m ≥2L-1,因此a 1n x -+c 在机器里存放时占的位数多于L 位,于是发生溢出,只能存放n x 的右后L 位.这个数值恰是模m=2L 的剩余,即n x .这就减少了除法运算,而实现了求同余式.经常取模m=2L (L 为计算机尾部字长),正是利用了溢出原理来减少除法运算.由式(1)产生的n x (n=1,2,……),到一定长度后,会出现周而复始的周期现象,即{n x }可以由其某一子列的重复出现而构成,这种重复出现的子列的最短长度称为序列n x 的周期.由式(1)不难看出,{n x }中两个重复数之间的最短距离长度就是它的周期,用T 代表周期.周期性表示一种规律性,它与随机性是矛盾的.因此,通常只能取{n x }的一个周期作为可用的随机序列.这样一来,为了产生足够多的随机数,就必须{n x }的周期尽可能地大.由前所述,一般取m=2L ,这就是说模m 已取到计算机能表示的数的最大数值,意即使产生的随机数列{n x }的周期达到可能的最大数值,如适当地选取参数0x ,a ,c 等,还可能使随机数列{n x }达到满周期.三、非均匀分布随机数的产生3.1 一般通用方法3.1.1组合法组合法的基本思想是把预定概率密度函数f ( x ) 表为其它一些概率密度的线性组合.而这些概率密度的随机抽样容易产生.通过这种避难就易的手段我们也许可以达到较高的输出速度和较好的性能.若分布密度函数f ( x ) 能表为如下式(2)所示的函数项级数的和,1()()i i i f x p f x ∞==∑ (2) 其 中1ii p ∞=∑,诸f( x )皆为概率密度函数.则依如下步骤可产生分布为f ( x )一次抽样. ( 1 ) 产生一个随机自然数I , 使I 服从如下分布律:P ( I = i ) = p i i = 1 , 2 , 3……( 2 ) 产生服从f I ( x )的随机数0X证明利用全概率公式,有:11()()()()()i i i i P x X x dx P I i P x X x dx I i p f x dxf x dx∞=∞=<≤+==<≤+|===∑∑故X 服从f ( x ) 分布.我们以产生双指数(或拉普拉斯)分布的随机数为例来简单说明这种方法.双指数分布具有 概率密度函数f ( x ) = 0 . 5x e -, 如图2 :图2 双指数密度函数f ( x ) 可表为:()0.5()0.5()l r f x f x f x =+ (3)其中()r f x 是指数分布,()l f x 是指数分布的对称分布.故产生双指数分布的抽样可按如下方法: 产生U 1 , U 2~U ( 0 , 1 ) ;若U 1 > 0 . 5 , 则令X = I n U 2,否则X = - I n U 2. 在式(2) 中, 若i →∞, 有p i → 0 ,则可用函数列{()}i i p f x 的前有限项和逼近f ( x ).这是一种近似的方法,与通常的函数逼近原理相同.只要近似的精度 ( 在某种“精度”的意义之下) 达到要求,我们就可以采用近似的方法 .使用组合法时,各f i ( x ) 的抽样应该容易产生,故选用合适的概率密度函数族{ f i ( x )}把任意连续分布表为式(2) ,乃是使用组合法的关键.3.3.2 概率密度变换法这是一种比较新的通用随机数产生方法.其主要的目的是对一般的f(x)找出较好的覆盖函数以达到较高的效率.我们知道,对某一特定的概率密度f(x),我们可以使用最优化技术找到好的覆盖函数.但对于一般情况,我们只能期望产生效率尚可的覆盖函数. H O R M A N N 用概率密度变换的方法生成一曲边梯形作为覆盖函数.其原理如下:使用一个变换函数T (x)把预定密度函数f ( x ) 变换为h ( x ) = T ( f ( x ) ) ,用一个分段线性函数l ( x )覆盖h ( x ),如图2 - 4 左图; h ( x ) 若是上凸的,则T1-( l ( x ) )将是f ( x ) 的一个较好的覆盖函数,图3 概率密度变换法原理图这个方法在选择合适的T ( x ) ( l o g ( x ) 或1 / x a等) 后,能产生随机数包括了较多的分布类型.这个方法有较短的预处理时间,但需要较多的函数计算,不太适合硬件实现.此外,A h r e n s l用每段为常数的分段函数作为覆盖函数.L e y d o l d基于r a t i o - o f - u n i f o r m s 的方法也是一个通用算法.还有一种近似的方法,其产生的随机数与指定分布的随机数具有相同的前四阶矩,但概率分布不一定相同.这里就不详细介绍了.3.2 我们的方法当前的通用算法的问题是效率不能任意提高,不够灵活. 通常产生每个所需随机数X需以较大的概率计算f ( x )等函数.我们认为在速度要求非常高的场合,计算f ( x )是不利的,尤其以硬件进行函数计算是十分不利的.针对己有通用算法的不足,我们提出了基于组合法的通用算法.主要目的是尽可能地减少三角、指数、对数等超越函数的计算,以便硬件实现.产生任意连续分布随机数的高效舍选算法本文提出一种通用算法,可视需要使效率接近1 , 而且f ( x ) 的计算概率可任意小. 这些优点的取得是以长的预处理时间为代价的.在需要产生大量随机样本的场合( 例如通信系统的误码率测试,可能需要数小时乃至数天的仿真时间) ,本算法将有很大的优势,尽管有看法认为只有能用简单代码实现的算法才会被经常使用.3.2.1 算法原理假定预定的连续概率密度函数f ( x ) 为单峰的( 这是实际的大多数情况) ,已知其峰值点为m .一般f ( x ) 不关于x =m 对称,如图2 -5 .我们假定f ( x ) 定义在有界的区间[ a , b ] 上( 上文说过,对正态分布这类定义区间无限的情况,我们把这个区间取得足够大就可以了) . 直线X=m把f ( x ) 曲线与X轴所围面积分为左右两部分,我们把左右两部分各等分为K份,一共得到2 K个曲边梯形.并用2 K个矩形各自覆盖相应的曲边梯形.如图4所示( 图中各均分为四份) .R i , L i ( i = 1 , 2 , . . . , K -1 )是分点.并令R0=L=m,L k = a,Rk= b .图4 均分f ( x ) 曲 线与X 轴所围面积我们的想法是利用舍选法的几何意义,分别在上述 2 K 个曲边梯形内均匀投点,从而使随机点在f ( x ) 曲线与x 轴所围的整个区域中均匀分布,这样即可产生f ( x ) 的抽样X . 而在曲边梯形内均匀投点可使用简单舍选法:先在各个矩形内均匀投点,再选出落于相应曲 边梯形内的点. 这种投点法浪费的点只位于各个矩形的一角, 显然效率大大高于简单舍选法.最为重要的是:随着K 的增大,效率会不断提高.另外,只有当投点位于曲边梯形的曲边之下时, 才需计算f ( x ) ,而且计算f ( x ) 概率是随着K 的增加而减小的.我们每次“ 按概率”随机选中一个曲 边梯形进行投点. 这需要两步完成:先选择左边还是右边,再于此边的K 个曲边梯形中选择一个.这里的概率显然就是面积,这可以从以下的推导中看出来.为清晰起见,我们先阐述随机数的产生法,而把面积的均分这个预处理过程置于随后.3.2.2 算法推导令()mP f x dx -∞=⎰为左边面积.则左边各曲边梯形面积皆为 P / K ,右边各曲边梯形面积皆为( ( I -P ) / K . f ( x ) 可表为: 12111()()()K Ki i i i P P f x f x f x K K ==-=+∑∑ (4) 诸ji f ( x ) ( j = 1 , 2 ; i = 1 , 2 . . . k ) 皆为一腰为曲边的梯形形状的概率密度函数.依如下步骤可产生分布为f ( x ) 的一次抽样:S t e p l :产生一个随机自然数J ,使J 服从如下两点分布: P ( J = 1 ) = P , P ( J = 2 ) = 1 - P : S t e p 2 :产生一个随机自然数I , 使I 服从如下均匀分布律:P ( I = i ) = 1 / K , i = 1 , 2 . . . . K ;S t e p 3 : 用基本舍选法产生概率密度为f ( x ) 的随机数X .证明利用全概率公式,有: 2111211()()()(,)1(()())()Kj i K Ki i i i P x X x dx P J j P I i P x X x dx J j I i P P f x f x dx K K f x dx ====<≤+===<≤+∣==-=+=∑∑∑∑故x 服从 f ( x ) 分布.下面完整地描述这个方法:S t e p l( 产生J ) :S t e p l . l 产生[ 0 , 1 ] 上的均匀随机数U 1 ;S t e p 1 . 2若U 1 < P ,则返回J = 1 , 否则返回J = 2 ;S t e p 2( 产生I ) :S t e p 2 . l 产生 [ 0 , I ] 上的均匀随机数U 2 ;S t e p 2 . 2 21;I kU x =+⎢⎥⎢⎥⎣⎦⎣⎦表示不大于x 的最大整数.产生 ji f ( x ) 的样本需区别j = 1 与j = 2 两种情况. 图2 - 6 示出j = 2 时一 典型的ji f ( x ) , 用简单舍选法产生其抽样,覆盖函数为矩形. 首先产生一个[ 0 , R i ] 的均匀数, 如它属于[ 0 , R 1i -] 小无需再产生y 轴方向的均匀随机数,接受此均匀数即可;否则还需产生一个Y 轴方向的均匀随机数进行投点,那些落在曲边下方的点被接受,投在矩形右上角的点被舍弃.同理易得j = 1 时的产生法.图5 典型的ji f ( x ) j=2整个S t e p 3 如下:S t e p 3( 产生X ) :i f J = =1{ l o o p :产生[ 0 , 1 ] 上的均匀随机数U 3 , W = ( L 0 - L 1 ) U 3 + L 1 : i f W> L 1i -,返回 X = W;e l s e { 产生[ O , l ] 上的均匀随机数V ;i f f ( W) - f ( L 1) < ( f ( L 1j - ) - f ( L 1 ) ) V 返回X = W; e l s e 舍弃W ,重复l o o p ;} }e l s e{ l o o p : 产生[ 0 , 1 ] 上的 均匀随机数U 3 , W = ( R 1 - R o ) U 3 + R o ;i f W< R 1i -,返回 X = W;e l s e {产生[ 0 , 1 ] 上的均匀随机数V ;i f f ( W) - f ( R 1) C ( f ( R 1I - ) - f ( R 1) ) V , 返回X = W; e l s e 舍弃W ,重复l o o p ;} }均匀随机数U 2 实际上可由U 1 变换得到, U 3 可由均匀数U2变换得到. 例如从U1 产生U 2 的方法是:当J = l 时, U 1 在[ 0 , P ] 上均匀分布, 故可令U 2 = U l / P ;当J = 2 时, U 1在[ P , 1] 上均匀分布, 故可令U 2 = ( U 1 - P ) / ( 1 - P ) . 从U 2 产生U 3 的方法是:当I = i 时, U 2 在 [ i / K , ( i + l ) / K ]上均匀分布, 故可令U 3 = K ( U 2 - i / K ) . 这样的做法节省了均匀随机数,增加了一些乘法和除法运算.对F P G A 等并行处理的硬件来说,产生均匀随机数是便宜的,除法运算是耗费的,所以我们不提倡减少均匀数的做法. 而对有C P U 的硬件来说, 减少均匀随机数意味着减少了过程调用,也许是值得的. 再介绍预处理过程.各分点需解下列递推方程求得:从i=1开始求解,直至i = K - 1 .这些方程可事先利用软件求解.3.2.3 算法性能分析影响随机数产生速度的主要因素之一是f ( x ) 的计算,故把产生每个抽样平均计算f ( x )的次数 ( 计算概率)做为一个性能指标.另外舍选法的平均效率也作为一个性能指标,这个指标反映了每产生一个随机数所需的均匀数个数.产生每个样点X 需计算f ( x ) 的平均概率P f 可利用全概率公式计算:其中10i i iL L L L ---的分母是左边第i 个曲边梯形的下底长,分子是下底与上底的差,这个比值就是在此曲边梯形内投点时计算f ( x ) 的概率.10i i i R R R R ---的意义相仿. 舍选法的平均效率” 可利用全概率公式计算:11()()11(1)()()L R KK i i L R A i A i P P K B i K B i η===+-∑∑ 诸(),(),(),()L L R R A i B i A i B i 分别表示左边各曲边梯形面积、左边各矩形面积、右边各曲边梯形面积和右边各矩形面积.在不同的K 值下,计算了算法用于产生正态分布、 指数分布、 瑞利分布三种标准分布时的上述两个性能参数.各个概率密度函数如下:正态分布:2())2x f x =- 指数分布:()x f x e -= 瑞利分布: 2()exp()48x x f x =- 结果如下图6 :左图反映出概率密度函 数的计算概率P f 随K 的增大而减小, 最终趋于零,例如当K = 1 0 2 4 时, P f 已 非常小;右图反映出 舍选法的平均效率随K 的 增加而提高, 最终趋于 1 , 也就是三个均匀随机数产生一个预期的随机数.我们可根据实际情况选择合适的K 值.图6 计算概率密度函数的概率3.3正态分布的随机数的产生下面提出了一种已知概率密度函数的分布的随机数的产生方法,以典型的正态分布为例来说名任意分布的随机数的产生方法.如果一个随机数序列服从一维正态分布,那么它有有如下的概率密度函数:22()2()xf xμσ--=其中μ,σ(>0)为常数,它们分别为数学期望和均方差,如果读者对数学期望和均方差的概念还不大清楚,请查阅有关概率论的书.如果取μ =0,σ =0.2,则其曲线为图7 正态分布的概率密度函数曲线从图中可以看出,在μ附近的概率密度大,远离μ的地方概率密度小,我们要产生的随机数要服从这种分布,就是要使产生的随机数在μ附近的概率要大,远离μ处小,怎样保证这一点呢,可以采用如下的方法:在图7的大矩形中随机产生点,这些点是平均分布的,如果产生的点落在概率密度曲线的下方,则认为产生的点是符合要求的,将它们保留,如果在概率密度曲线的上方,则认为这些点不合格,将它们去处.如果随机产生了一大批在整个矩形中均匀分布的点,那么被保留下来的点的横坐标就服从了正态分布.可以设想,由于在μ处的f(x)的值比较大,理所当然的在μ附近的点个数要多,远离μ处的少,这从面积上就可以看出来.我们要产生的随机数就是这里的横坐标.基于以上思想,我们可以用程序实现在一定范围内服从正态分布的随机数.程序如下:double Normal(double x,double miu,double sigma) //概率密度函数{return 1.0/sqrt(2*PI*sigma) *exp(-1*(x-miu)*(x-miu)/(2*sigma*sigma));}double NormalRandom(double miu,double sigma,double min,double max)//产生正态分布随机数{double x;double dScope;double y;do{x = AverageRandom(min,max);y = Normal(dResult, miu, sigma);dScope = AverageRandom(0, Normal(miu,miu,sigma));}while( dScope > y);return x;}参数说明:double miu:μ,正态函数的数学期望double sigma:σ,正态函数的均方差double min,double max,表明产生的随机数的范围用如上方法,取μ=0,σ=0.2,范围是-1~1产生400个正态随机数如图8所示:图8 μ=0,σ=0.2,范围在-1~1时的400个正态分布的随机数分布图取μ=0,σ=0.05,范围是-1~1产生400个正态随机数如图9所示:图9 μ=0,σ=0.05,范围在-1~1时的400个正态分布的随机数分布图从图8和图9的比较可以看出,σ越小,产生的随机数靠近μ的数量越多,也说明了产生的随机数靠近μ的概率越大.我们,先产生4000个在0到4之间的正态分布的随机数,取μ=0,σ=0.2,再把产生的数据的数量做个统计,画成曲线,如下图10所示:图10 μ=0,σ=0.2,范围在0~4时的4000个正态分布的随机数统计图从图10中也可以看出,在靠近2处的产生的个数多,远离2处的产生的数量少,该图的轮廓线和概率密度曲线的形状刚好吻合.也就验证了该方法的正确性.有了以上基础,也就用同样的方法,只要知道概率密度函数,也就不难产生任意分布的随机数,方法都是先产生一个点,然后进行取舍,落在概率密度曲线下方的点就满足要求,取其横坐标就是所要获取的随机数参考文献:[1] 肖云茹.概率统计计算方法[M].天津:南开大学出版社,1994.[2]程兴新.曹敏.统计计算方法EM3.北京:北京大学出版社,1989.[3]王永德等.随机信号分析基础.北京:电子工业出版社,2 0 0 3.[4]皇甫堪等. 现代数字信号处理. 国防科技大学电子科学与工程学院内部印刷,2 0 0 2.。
C语言中产生随机数的方法在C语言中,可以使用多种方法产生随机数。
下面将介绍三种常用的方法:使用rand函数、使用srand函数、使用时间戳作为种子。
1. 使用rand函数:rand函数是C标准库中用于产生伪随机数的函数,其返回一个介于0至RAND_MAX之间的随机整数。
使用rand函数需要包含stdlib.h头文件。
```#include <stdio.h>#include <stdlib.h>int maiint i, n;printf("输入一个整数:");scanf("%d", &n);//产生n个随机数for (i = 0; i < n; i++)printf("%d\n", rand();}return 0;```2. 使用srand函数:srand函数用于设置rand函数的种子,通过设置不同的种子可以获取不同的随机数序列。
使用srand函数需要包含stdlib.h头文件。
```#include <stdio.h>#include <stdlib.h>int maiint i, n;printf("输入一个整数:");scanf("%d", &n);//设置种子为当前时间//产生n个随机数for (i = 0; i < n; i++)printf("%d\n", rand();}return 0;```3.使用时间戳作为种子:```#include <stdio.h>#include <stdlib.h>int maiint i, n;printf("输入一个整数:");scanf("%d", &n);//获取当前时间的时间戳//产生n个随机数for (i = 0; i < n; i++)printf("%d\n", rand();}return 0;```以上就是在C语言中产生随机数的三种常用方法。
产生不重复随机数方法1.使用数组一种简单的方法是使用数组来存储已经生成的随机数。
首先,创建一个大小为n的数组,其中n是要生成的随机数的数量。
然后,使用一个循环从1到n生成随机数,并将其存储在数组中。
在生成每个随机数之前,检查它是否已经存在于数组中。
如果是,则重新生成另一个随机数,直到找到一个不重复的随机数为止。
这种方法的优点是简单易懂,但是当需要生成的随机数数量较大时,性能可能会较差。
2.使用哈希表哈希表是另一种常见的方法来生成不重复的随机数。
哈希表是一种数据结构,可以在O(1)的时间复杂度内查找和插入元素。
首先,创建一个空的哈希表。
然后,使用一个循环从1到n生成随机数,并将其插入到哈希表中。
在插入之前,检查随机数是否已经存在于哈希表中。
如果是,则重新生成另一个随机数,直到找到一个不重复的随机数为止。
这种方法的优点是性能较好,但是需要额外的存储空间来存储哈希表。
3. Fisher–Yates洗牌算法Fisher–Yates洗牌算法是一种通用的随机排列算法。
它通过交换数组中的元素来生成不重复的随机数。
首先,创建一个长度为n的数组,并将数字从1到n存储在数组中。
然后,从最后一个元素开始,遍历整个数组。
对于每个元素,生成一个在当前元素之前的随机索引,并交换当前元素与随机索引处的元素。
这样,每个元素都有机会出现在第i个位置,其中i从1到n。
在每次交换之后,缩小随机数生成的范围,以避免重复生成相同的索引。
这种方法的优点是效率高,且不需要额外的存储空间。
4.使用加密算法生成随机数加密算法是一种非常安全的方法来生成随机数。
其中一个常见的加密算法是SHA-256算法。
通过使用一些种子值作为输入,并对其进行SHA-256加密,可以生成一个唯一的随机数。
这种方法的优点是生成的随机数具有较高的安全性和不可预测性,但是在一些情况下,性能可能较低。
随机数的产生方法瑞达路水瓶酒窝哥由于老师布置了产生随机数的作业,要求编一个程序能够产生0000到9999总共10000个不重复的随机数,可能大家在网上看了一些方法,都用了函数Rand与Brand的结合,可以产生10000个随机数,并且大家都是用公式(rand() % (b-a))+ a来约束产生随机数的范围和个数的,但是大家几乎忘了不能重复的要求,所以产生的随机数是有很多重复的,不能满足要求,鉴于这种情况,我把大众化随机数的产生方法以及自己的一点改进措施与大家共享如下:一、可重复随机数的产生方法:我们知道rand()函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统。
但是有一个函数srand()可以初始化这个种子函数。
1、函数rand()用法:说明:rand是包含在头文件stdlib.h中,跟stdio.h是一个道理,具体运用方法如下:代码:# include "stdio.h"# include "stdlib.h"int main(){int k;k=rand();printf("%d",k);return 0;}程序在编译软件中的运行截图过程如下:当运行这个程序时,我们会发现,产生的随机数永远都是一个值,例如我的电脑是41,这是因为计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。
(注意:小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了。
)rand()返回一随机数值的范围在0至RAND_MAX 间。
c语言随机数生成方法C语言是一门广泛应用于计算机编程领域的高级编程语言,其强大的功能和灵活性使其成为了许多程序员的首选语言。
在C语言中,随机数生成是一个非常常见的需求,本文将介绍C语言中随机数生成的方法。
C语言中的随机数生成函数是rand(),该函数可以生成一个0到RAND_MAX之间的随机整数。
但是,如果我们需要生成一个指定范围内的随机数,该怎么办呢?下面是一些常用的方法:1. 生成0到n之间的随机整数要生成0到n之间的随机整数,我们可以使用rand()函数和取模运算符%。
具体方法如下:int random_num = rand() % (n + 1);这里的n是我们需要生成的最大整数,加1是为了保证生成的随机数不会超过n。
2. 生成m到n之间的随机整数如果我们需要生成m到n之间的随机整数,我们可以使用rand()函数和取模运算符%。
具体方法如下:int random_num = rand() % (n - m + 1) + m;这里的m和n分别是我们需要生成的最小整数和最大整数,n-m+1是为了保证生成的随机数不会超过n,再加上m是为了保证生成的随机数不会小于m。
3. 生成0到1之间的随机小数要生成0到1之间的随机小数,我们可以使用rand()函数和类型转换。
具体方法如下:double random_num = (double)rand() / RAND_MAX;这里的RAND_MAX是一个常量,表示rand()函数能够生成的最大整数。
我们将rand()函数生成的整数转换成double类型,再除以RAND_MAX,就可以得到0到1之间的随机小数。
4. 生成m到n之间的随机小数如果我们需要生成m到n之间的随机小数,我们可以使用rand()函数和类型转换。
具体方法如下:double random_num = (double)rand() / ((double)RAND_MAX / (n - m)) + m;这里的m和n分别是我们需要生成的最小数和最大数,RAND_MAX 是一个常量,表示rand()函数能够生成的最大整数。
⽣成不重复的随机数的三种⽅法下⾯我以⽣成1-10之间的10个不重复的随机数为例介绍⽣成不重复的随机数的三种⽅法:1,通过while循环来实现通过while循环不停的⽣成随机数,直到⽣成⼀个不重复的为⽌,这种⽅法⽐较容易想到,但是效率也⽐较低下,实例代码如下:static void Main(string[] args){int[] result = new int[10];int tmp = -1;Random random = new Random();bool repeat = false;for (int i = 0; i < 10; i++){repeat = true;while (repeat){repeat = false;tmp = random.Next(1, 11);for (int j = 0; j < i; j++){if (tmp == result[j]){repeat = true;break;}}}result[i] = tmp;}for (int i = 0; i < 10; i++)Console.WriteLine(result[i].ToString());}2,通过for循环来实现⽅法1使⽤了多处循环嵌套,效率⼗分低下,所以我应⽤⼀定的技巧来减少循环嵌套,来达到提⾼程序效率的⽬的。
主要思路是如果检测到重复,就把循环变量减1,这样来重新进⾏⼀次循环,重新⽣成⼀个随机数,直到⽣成⼀个不重复的随机数为⽌,实例代码如下:static void Main(string[] args){int[] result = new int[10];int tmp = -1;Random random = new Random();bool repeat = false;for (int i = 0; i < 10; i++){repeat = false;tmp = random.Next(1, 11);for (int j = 0; j < i; j++){if (tmp == result[j]){repeat = true;break;}}if (!repeat){result[i] = tmp;}else{i = i - 1;//循环变量-1}}for (int i = 0; i < 10; i++)Console.WriteLine(result[i].ToString());}这个⽅法减少了⼀层循环嵌套,效率上有⼀定的改善!3,通过随机排序来实现这种⽅法彻底的颠覆了⽅法1和2的基本思路,先初始化⼀个包含数字1-10的数组,然后每次循环取⼀个随机位置,将这个位置的元素和最后⼀个位置的元素交换!实例代码如下:static void Main(string[] args){int[] result = new int[10];for (int i = 0; i < 10; i++)result[i] = i + 1;for (int j = 9; j > 0; j--){Random r = new Random();int index = r.Next(0, j);int temp = result[index];result[index] = result[j];result[j] = temp;}for (int i = 0; i < 10; i++)Console.WriteLine(result[i].ToString());}这种⽅法消除了循环嵌套,效率上获得了进⼀步的改善,但是也有⼀定的限制,如果要⽣成5个1-10之间的随机数,那这种打乱顺序的⽅法就⽆法使⽤了!总结:⽅法1效率⽐较低下,⼀般不推荐使⽤!⽅法2⽐较通⽤,效率⾼于⽅法1,但是效率低于⽅法3⽅法3虽然效率⽐较⾼,但是只能应⽤与特定的情况下!请⼤家多多指教啊!。
我在vc下做一个猜数字小游戏时要产生一个四位随机不重复数字,费了好大力气才弄好。
希望对有相同需求的,有些帮助
结果图
利用srand()函数以当前时间秒为种子,rand()函数以这个种子产生随机数。
程序中为了看效果,先输出后判断并加了延时
程序代码如下
#include <stdlib.h> /*包含rand() srand()函数的标准库*/ #include <stdio.h>
#include <time.h> /*包含time() 函数的标准库*/
void main( void )
{
inti,j;
intra[3];
int flag;
do{
srand( (unsigned)time(0) );
i=rand()%8977+1023;
ra[0]=i/1000;
i%=1000;
ra[1]=i/100;
i%=100;
ra[2]=i/10;
i%=10;
ra[3]=i;
for(i=0;i<4;i++)
printf("%d ",ra[i]);
printf("\n");
if(ra[0]!=ra[1]&&ra[0]!=ra[2]&&ra[0]!=ra[3]&&ra[1]!=ra[2]&&ra[1]!=ra[3]&&ra[2]!=ra[3]) flag=0;
else
flag=1;
for(i=0;i<300000000;i++) /*延时*/ ;
}while(flag);
}。