简单谈谈关于C++中大随机数的问题

前言

大家都知道C++的随机数最大值是RAND_MAX,在头文件<stdlib.h>中定义。在windows平台下的VS是0x7fff,在MacBook的XCode是int的最大值。看来不同的平台是不同的。但是windows的是在太小了。

先上一个平时的随机函数:

int littleRand(int min, int max)
{
 //考虑到不同平台下RAND_MAX可能不等于0x7fff,所以不能把RAND_MAX*RAND_MAX,以免int爆掉 

 if (min > max)
 {
 min = max;
 } 

 int randV = rand() % (max - min + 1); 

 int randResult = min + randV;
 return randResult;
} 

想优化一下:想着两个相乘,最大值是1亿,而且都是随机,就应该是均等的。

int bigRand(int min, int max)
{
 //考虑到不同平台下RAND_MAX可能不等于0x7fff,所以不能把RAND_MAX*RAND_MAX,以免int爆掉 

 if (min > max)
 {
 min = max;
 } 

 int rand1 = rand() % 10000;
 int rand2 = rand() % 10000;
 int randV = (rand1 * rand2) % (max - min + 1); 

 int randResult = min + randV;
 return randResult;
} 

于是我运行了100万次,生成10以内的随机数,统计一下出现的次数。

int main()
{
 srand(time(0));
 std::map<int, int> a;
 std::map<int, int> b;
 for (int i = 0; i < 1000000; i ++)
 {
 a[bigRand(1, 10)]++;
 b[littleRand(1, 10)]++;
 }
 for (int i = 1; i <= 10; ++ i)
 {
 cout << i <<": \t"<< a[i] << " \t " << b[i] << endl;
 } 

 return 0;
} 

结果:

左边的是大随机数的次数,右边的是原来的。

可以看出,右边的比较正常,基本上是平均的。

而左边的,明显隔一个就大一点。等于1的特别高。至于怎么产生的我也想不通。

不过可以想象一下,缩小范围。就随机1和2。

1和2的概率都是0.5,两个数相乘是4.我们可以得到1-4范围的随机数。

但是概率明显不是均等的。假如执行两次,1和2都出现

就可以等到1:1次,2:2次,3:0次,4:1次。

明显,相乘的肯定是有差别的.

来,再把小时候妈妈叫我的乘法口诀看一遍。

std::map<int, int> r;
for(int i = 0; i < 10; ++i)
{
 for (int j = 0; j < 10; ++j) {
 r[i * j %10]++;
 }
}
for (int i = 0 ; i < 10; ++i) {
 cout << i <<"\t"<< r[i] << endl;
} 

结果:

0 27
1 4
2 12
3 4
4 12
5 9
6 12
7 4
8 12
9 4

那应该怎么搞呢,其实应该用移位的方法。你算出来的数是10进制的话,每次向左移动1为,就是乘以10,例如我上面的代码,

int bigRand(int min, int max)
{
 if (min > max)
 {
 min = max;
 } 

 int rand1 = rand() % 10000;
 int rand2 = rand() % 10000;
 int randV = (rand1 * 10000 + rand2) % (max - min + 1);//改成这样 

 int randResult = min + randV;
 return randResult;
} 

10000以下和10000以上完全不相干,两次随机不相干。只有这样才能使正确的随机。

其实就是求模的时候,模式多少,第一次随机就要乘以多少。rand1乘以的是rand2的模。

百度了一下其他人的随机数。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
unsigned long ulrand(void) {
 return (
 (((unsigned long)rand()<<24)&0xFF000000ul)
 |(((unsigned long)rand()<<12)&0x00FFF000ul)
 |(((unsigned long)rand() )&0x00000FFFul));
}
int i;
unsigned long ul;
void main() {
 srand(time(NULL));
 for (i=0;i<10;i++) {
 ul=ulrand();
 printf("%010lu 0x%08x\n",ul,ul);
 }
} 

还有这个简单点的:

int BigRand()
{
 return RAND_MAX*rand() + rand();
} 

其实都是通过移位的方式,移出那个随机数的最大值就行。

不过有个问题要考虑的,就是跨平台问题。不同平台的整形的长度可能不同,RAND_MAX也可能不同。总是移位,可能会出现数组越界。

所以为了安全起见还是用我写的两个10000最大值的随机数吧。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • C++ 随机数与随机种子数的实例

    C++ 随机数与随机种子数的实例 实现效果图: 实例代码: #include <stdlib.h> #include <iostream> #include <ctime> using namespace std; void Test() { int ran_num = 0; cout<<"不指定seed, "; for(int i=0; i<10;i++) { ran_num = rand()%6; cout<<ran

  • C++基于随机数实现福彩双色球的方法示例

    本文实例讲述了C++基于随机数实现福彩双色球的方法.分享给大家供大家参考,具体如下: 这是前段时间写的福彩双色球一个小应用 本来可以一个文件搞定,反正也没多大,就分开了. 头文件doubleColorBallR2.h #ifndef _DoubleColorBallR2_h #define _DoubleColorBallR2_h #include <iostream> #include <stdio.h> #include <vector> #include <

  • C/C++产生指定范围和不定范围随机数的实例代码

    一. 不指定范围产生随机数用到函数rand(),函数原型为int rand(),无参数.此时会产生一个介于0~RAND_MAX间的整数.RAND_MAX的大小可以查看,在include文件夹(linux在usr目录.windows在安装目录)的stdlib.h可以看到,linux下其值为2147483647(),其值与具体系统有关.参考代码: 复制代码 代码如下: #include<stdio.h>#include<stdlib.h> int main(){        int

  • C++产生随机数的实现代码

    C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C++里没有自带的random(int number)函数. (1) 如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间.RAND_MAX值至少为32767.例如: 复制代码 代码如下: #include<stdio.h>#include <iostream> 复制代码 代码如下: int _tmain(int argc,

  • C++编写生成不重复的随机数代码

    C++编写生成不重复的随机数代码 vector<int> getRandom(int total) { srand((int)time(NULL)); std::vector<int> input = *new std::vector<int>(); for (int i = 0; i < total; i++) { input.push_back(i); } vector<int> output = *new vector<int>();

  • C/C++产生随机数函数简单介绍

    计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子.(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了.) 我们知道rand()函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,

  • C语言/C++如何生成随机数

    本文分享了C语言/C++如何生成随机数的具体实现方法,供大家参考,具体内容如下 C语言/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里没有自带的random(int number)函数. (1) 如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间.RAND_MAX定义在stdlib.h, 其值为2147483647. 例如: #include<stdio.h> #i

  • C++随机数生成实例讲解

    如果让你用C++来生成0--N-1之间的随机数,你会怎么做?你可能会说,很简单,看: srand( (unsigned)time( NULL ) ); rand() % N; 仔细想一下,这个结果是随机的吗(当然,我们不考虑rand()函数的伪随机性)? 不是的,因为rand()的上限是RAND_MAX,而一般情况下,RAND_MAX并不是N的整数倍,那么如果RAND_MAX % = r,则0--r之间的数值的概率就要大一些,而r+1--N-1之间的数值的概率就要小一些.还有,如果N > RAN

  • C语言/C++中如何产生随机数

    C语言/C++怎样产生随机数:这里要用到的是rand()函数, srand()函数,和time()函数. 需要说明的是,iostream头文件中就有srand函数的定义,不需要再额外引入stdlib.h;而使用time()函数需要引入ctime头文件. 使用rand()函数获取一个随机数如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间.RAND_MAX定义在stdlib.h, 其值为2147483647. 例子

  • 简单谈谈关于C++中大随机数的问题

    前言 大家都知道C++的随机数最大值是RAND_MAX,在头文件<stdlib.h>中定义.在windows平台下的VS是0x7fff,在MacBook的XCode是int的最大值.看来不同的平台是不同的.但是windows的是在太小了. 先上一个平时的随机函数: int littleRand(int min, int max) { //考虑到不同平台下RAND_MAX可能不等于0x7fff,所以不能把RAND_MAX*RAND_MAX,以免int爆掉 if (min > max) {

  • 简单谈谈原生js的math对象

    Math对象方法 //返回最大值 var max=Math.max(95,93,90,94,98); console.log(max); //返回最小值 var min=Math.min(95,93,90,94,98); console.log(min); //向上取整 console.log(Math.ceil(2.2)); console.log(Math.ceil(-2.2)); //向下取整 console.log(Math.floor(2.2));//2 console.log(Mat

  • 简单谈谈require模块化jquery和angular的问题

    require 模块化开发问题,正常自己写的模块 是exports 导出一个模块 //模块化引入jquery 不同和问题 require 引入jquery swiper .... 插件和库的时候需要 require.config({ baseUrl:"js/libs", //文件夹目录相对与html的位置 paths:{ 'jquery':"jquery-1.9.1" //插件或库的文件名 'swiper':"文件名/swiper" //当每个插

  • 简单谈谈vue的过渡动画(推荐)

    在vue中,实现过渡动画一般是下面这样: <transition name="fade"> <div></div> </transition> 用一个transition对元素或者组件进行封装. 在过渡的时候,会有 4 个(CSS)类名在 enter/leave 的过渡中切换. 1.v-enter: 定义进入过渡的开始状态.在元素被插入时生效,在下一个帧移除. 2.v-enter-active: 定义进入过渡的结束状态.在元素被插入时生效

  • react系列从零开始_简单谈谈react

    react算是目前最火的js MVC框架了,写一个react系列的博客,顺便回忆一下react的基础知识,新入门前端的小白,可以持续关注,我会从零开始教大家用react开发一个完整的项目,也会涉及到webpack,node等前端知识,每天会更新一篇.这篇react的系列博客会覆盖react目前的所有知识点: 一.React基础 1.React 虚拟DOM概念,React的性能高效的核心算法 2.React组件,理解什么叫组件化 3.React组件嵌套 4.JSX内置表达式 5.React的生命周

  • 简单谈谈React中的路由系统

    React中的路由系统 提起路由,首先想到的就是 ASPNET MVC 里面的路由系统--通过事先定义一组路由规则,程序运行时就能自动根据我们输入的URL来返回相对应的页面.前端中的路由与之类似,前端中的路由是根据你定义的路由规则来渲染不同的页面/组件,同时也会更新地址栏的URL.本篇文章要介绍的是React中经常使用到的路由,react-router主要使用HTML5的history API来同步你的UI和URL. react-router的最新版本是v4.1.1,由于4.0版本和之间的版本A

  • 简单谈谈Core Animation 动画效果

    在开始之前呢,先了解一下UIView和CALayer大体的区别(重点列举了以下四点): •UIView 继承自 UIResponder,因此UIView 可以处理响应事件,而CALayer继承自NSObject,所以它只是负责内容的创建,绘制. •UIView 负责对内容的管理,而CALayer则是对内容的绘制 •UIView 中有关位置的属性只有frame.bounds.center,而CALayer除了具备这些属性之外还有anchorPoint.position. •通过修改CALayer可

  • 简单谈谈Struts动态表单(DynamicForm)

    动态表单的含义是不要手动定义,直接在配置文件中进行定义. 1.手动进行定义 <form-beans > <form-bean name="userForm" type="org.apache.struts.action.DynaActionForm"> <!-- 该表单的属性是配置出来的 --> <form-property name="username" type="java.lang.Str

  • 简单谈谈JS中的正则表达式

    1.正则表达式包括两部分 ①定义正则表达式的规则: ②正则表达式的模式(i/g/m): 2.声明正则表达式 ① 字面量声明: var reg = /表达式规则/表达式模式: eg:var reg = /white/g: ② 使用new关键字: var reg = new RegExp("表达式规则","表达式模式") eg: var reg = new RegExp("white","g"): 3.正则表达式的三种模式 ① g

  • 简单谈谈Python中的json与pickle

    这是用于序列化的两个模块: • json: 用于字符串和python数据类型间进行转换 • pickle: 用于python特有的类型和python的数据类型间进行转换 Json 模块提供了四个功能:dumps.dump.loads.load pickle 模块提供了四个功能:dumps.dump.loads.load import pickle data = {'k1':123, 'k2':888} #dumps可以将数据类型转换成只有python才认识的字符串 p_str = pickle.

随机推荐