当前位置: 首页 > news >正文

【c++】rand()随机函数的应用(二)——舒尔特方格数字的生成

目录

一、舒尔特方格简介

二、如何生成舒尔特方格

(一)线性同余法

1、利用线性同余法生成随机数序列的规律

(1) 当a和c选取合适的数时,可以生成周期为m的随机数序列

(2) 种子seed取值也是有周期的

2、利用线性同余法生成5阶舒尔特方格的程序

(1)先验证当x0不变时,生成的随机数序列是有周期的

 (2)验证seed值x0也具有周期性

 (3)生成5维舒尔特方格数字

 (二)利用rand()函数

1、rand()函数搭配srand(time(NULL))函数

2、动态取模法

(1)初始化

(2)随机将a中数据存入b中

3、图解动态取模法

(1)a、b初始状态

(2)生成第一个随机数

(3)生成第二个随机数

(4)执行最后一步

4、动态取模法代码


rand()随机函数可以用来生成舒尔特方格数字。下边先介绍一下舒尔特方格。

一、舒尔特方格简介

舒尔特方格是用来测试和训练专注力的,百度百科的介绍如下:

舒尔特方格,画一张有25个小方格(规格1cm*1cm)的表格,将1~25的数字顺序打乱,填在表格里面,然后以最快速度从1数到25,要边读边指出,一人指读一人帮忙计时。

采用盯点法就可以随时训练的,在教室和家里,每天盯着某个点和物体看上几分钟就可以的,还可以采用舒尔特训练法。

运用这种方法的时候,可以自制几套卡片,绘制表格,任意填上数字。从 1开始,边念边指出相应的数字,直到25为止。同时诵读出声,施测者一旁记录所用时间。数完 25 个数字所用时间越短,注意力水平越高。以 12 —— 14 岁年龄组为例,能达到 16 "以上为优秀, 26 "属于中等水平, 36 "则需要进行强化提高。

注:百度百科上介绍的舒尔特方格是5维(5行5列)规格的,而实际维数是可变的,维数越高难度越大,1维2维太简单,一般不用。3维、4维属于初级难度,5维6维属于中级难度,7级及以上就属于难度比较高级的了。

二、如何生成舒尔特方格

5维舒尔特方格内数字的排列不是固定的,位置是随机的,运用排列组合的知识可以知道,一共有25!个不同的排列方式。用人工排列生成的方法显然是不可行的,那么用什么算法可以实现这个目的呢?下边介绍两种方法。

(一)线性同余法

在上一篇文章中介绍了线性同余生成随机数的方法。线性同余的公式如下所示:

x_{n+1}=(a*x_{n}+c) mod(m)​     (1)

其中a是乘法器,c是增值,m是模,这三个都是常数,x_{n}​是生成的随机数序列,当n=0时,x_{0}的值称为种子seed。

1、利用线性同余法生成随机数序列的规律

(1) 当a和c选取合适的数时,可以生成周期为m的随机数序列

周期为m的意思就是,在一个周期内,利用公式(1)迭代计算m次,正好可以把数字0~m-1每个数字都可以生成且只生成一次,而且最后一次迭代生成的数正好就是种子数x_{0}。迭代到第m+1次时,生成的数字和第一次迭代生成的数字x_{1}一样,再接着迭代就会重复上一个周期。生成一个周期内的数字排列顺序表面看是无规律,实际上是由公式(1)计算出来的,所以叫伪随机数。

还需要注意,并不是任意取一组a和c,就可以生成周期为m的伪随机数序列。a和c的取值是有限定条件的,条件如下图所示。

(2) 种子seed取值也是有周期的

利用公式(1),当a、c、m都确定后,当seed值选取不同时,生成的随机数序列也不同。但是需要注意,并不是任意取一个seed值,生成的随机数序列都不一样,seed取值也是有周期的,当随机数的周期是m时,seed的周期也是m。也就是seed=0时,和seed=m时,生成的随机数序列是一样的。也就是利用线性同余方法,生成不同的随机数序列最多有m种。

2、利用线性同余法生成5阶舒尔特方格的程序

 5阶舒尔特方格的数字范围为1~25,每个格子数字各不相同,排列顺序随机。所以可以考虑使用线性同余法。经过测试,发现当c=11,a=11时,利用线性同余计算出来的伪随机数序列的周期是25。

(1)先验证当x0不变时,生成的随机数序列是有周期的

编写一个给定x0=0,生成两个周期随机数的测试程序如下:

#include <iostream>
using namespace std;int main()
{int i,x0=0,a=11,c=11,m=25;	//确定a=11,c=11,m=25	for(i=0;i<m*2;i++)		//此循环用于生成2个周期内的随机数 {x0=(a*x0+c)%m;cout<<x0<<" ";}cout<<endl; return 0;
} 

下图是测试结果,图中黄色框内是第一个周期的25个随机数,绿色框内是第二个周期内的25个随机数。可以看出两个周期内的随机数排列顺序完全一致,因此说明当x0不变时,生成的随机数呈周期性变化。

 (2)验证seed值x0也具有周期性

编写一个x0从0增加到49(两个周期)时,每个seed值生成一个周期的随机函数序列,代码如下:

#include <iostream>
using namespace std;int main()
{int i,j,x0,a=11,c=11,m=25;	//确定a=11,c=11,m=25 for(j=0;j<m*2;j++) 			//此循环用于使种子值从0增加到49 {x0=j;cout<<"seed="<<x0<<":";		for(i=0;i<m;i++)		//此循环用于生成一个周期内 {x0=(a*x0+c)%m;cout<<x0<<" ";}cout<<endl; }	return 0;
} 

下图是测试结果如下图,从图中可以发现,seed值在0~24范围内(黄线以上),生成的25个随机数序列各不相同,而seed在25~49范围内(黄线以下)时的随机序列,与0~24范围内依次对应,完全一样,说明,seed值对随机序列的影响也是周期性的,周期也是25。 

 综上所述,利用基本的线性同余算法,对于5维舒尔特方格,最多只能生成25个不同的排列。

 (3)生成5维舒尔特方格数字

本例程序,将生成的25个5维舒尔特方格数字输出到一个csv文件内。因为利用线性同余算法生成的随机数范围为0~24,而5维舒尔特方格内的数字为1~25,所以只需将生成的随机数再加1即可。

#include <iostream>
#include <fstream>using namespace std;int main()
{int i,j,x0,a=11,c=11,m=25;	//确定a=11,c=11,m=25 ofstream oFile;				//新建一个ofstream文件oFileoFile.open("ShultGrid.csv",ios::out|ios::trunc);//打开oFile文件,文件名称为"ShultGrid.csv"for(j=0;j<m;j++) 			//此循环用于使种子值从0增加到49 {x0=j;oFile<<"舒尔特方格"<<x0;		for(i=0;i<m;i++)		//此循环用于生成一个周期内 {x0=(a*x0+c)%m;			if(i%5==0)			//每5个数字分成一行 {oFile<<endl;	}oFile<<x0+1<<",";	//生成的随机数为0~24,加1后变为1~25。输入一个",",代表光标移动到同一行的下一个单元格 }oFile<<endl<<endl; 		//最后一行回车,然后再空一行 }	return 0;
} 

以下是程序运行后,生成的csv文件部分舒尔特方格截图。

 (二)利用rand()函数

以上介绍了利用线性同余法生成舒尔特方格的方法,方法比较简单,但是最大的缺点是只能生成25个不同的排列。要想生成更多不同的排列,还需要用其他的方法。而利用rand()函数就是一种可行的方法。

1、rand()函数搭配srand(time(NULL))函数

在上一讲种介绍了,可以利用rand()搭配srand(time(NULL))函数,生成1~25的随机数,代码如下所示。

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
using namespace std;int main()
{int m,n;cin>>n>>m; 
//	srand(getpid());srand(time(NULL));while(1){cout<<rand()%(m-n+1)+n<<endl;Sleep(1000);}}

运行代码,输入n=1,m=25,生成的结果如下图所示。从图中可以看出,在前25个数中,有重复的数字,还缺了一些数字。这是因为rand()函数是以32768为模,在一个周期内可以生成0~32767范围内互不相同的随机数序列。但是rand()%25的结果就可能在0~25范围内会出现重复或者缺失的情况。

 所以,用这种方法是不可行的。

2、动态取模法

本例提出了一种新的方法实现不同维数舒尔特方格的生成方法,也需要用到rand()、srand()函数,在算法上采用动态取模方法。

动态取模算法的思路是:

(1)初始化

声明两个长度为25的一维数组a[25],b[25],数组a用来按顺序存放1~25数字,b用来存放从a中随机取出来的数字。用j表示数组b的角标,i表示数组a[]的角标,k表示需要更新数据的a[]的角标。

(2)随机将a中数据存入b中

从j=0开始,依次随机将a中的一个数字,存入到b[j]中,然后将a中角标i以后的有效数字依次向前移动一位。此时a[i]就被覆盖了,而a[24-j]那个位置的数据就无效了,下次取数字就不会再考虑这个位置。a中有效数字就是a中还没有被存入到b中的数字。a的角标i是用srand()搭配rand()%(25-j)随机生成的。此步关键代码为

srand(time(NULL));
i=rand()%(25-j);b[j]=a[i];a[i]=a[i+1];

模m=25-j,是可变的,因为每次从a中取走一个数字,a中的有效数字就减少了一个,所以生成的随机数范围就要减少1,也就是模m是依次减少1,是动态可变的,所以叫动态取模法。

3、图解动态取模法

(1)a、b初始状态

a、b初始化后的状态如下图所示。

(2)生成第一个随机数

假设第一次i=3,则把a[3]的值4赋给b[0],然后从i=3开始,到i=23结束,执行a[i]=a[i+1]进行数据更新。a、b数组执行生成随机数前后的对比如下图所示。图中a数组中有效的数字所占据的空间用绿色填充,无效的空间用白色填充。数组b中已经填入的随机数字用蓝色填充,没有填入数字的用白色填充。

(3)生成第二个随机数

假设第二次i=22,那么取出其中存储的数据24,放入b[1]中,然后从i=22开始,到i=22结束,执行a[i]=a[i+1]进行数据更新。a、b数组执行生成随机数前后的对比如下图所示。

 

(4)执行最后一步

执行到第25步时,a、b数组内的存储情况如下图所示。

 

4、动态取模法代码

#include <iostream>
#include<stdio.h>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <string>
using namespace std;int* diff_random(int m,int num)
{int a[num];//a数组用于按1-num顺序存放初始数字,b用于存放随机生成的舒尔特数字 int *b=new int[num];int i,j,k;	for(i=0;i<num;i++)//初始化初始数字数组 {a[i]=i+m;}srand(time(NULL));for(j=0;j<num;j++)			//利用无重复随机数算法生成舒尔特方格数组,j为生成数组的序号 {i=rand()%(num-j);		//生成数组a的随机序号,范围为0~num-j,用i表示 b[j]=a[i];				//将a[i]中存放的数字(也就是i+1)赋值给b[j]for(k=i;k<num-j-1;k++)	//将a[i]中存放的数字删除,将a[i+1]~a[num-j]的数字依次向前移动一个位置 {a[k]=a[k+1];}	}for(i=0;i<num;i++)			//初始化初始数字数组 {cout<<a[i]<<endl;}	return b;
}int main()
{int dim,num;//dim:舒尔特方格维数,num:方格个数 cout<<"请输入舒尔特方格维数:"<<endl;cin>>dim; num=dim*dim;int i;int *b=diff_random(1,num);ofstream oFile;//新建一个ofstream文件oFileoFile.open("ShultGrid1.csv",ios::out|ios::trunc);//打开oFile文件,文件名称为"ShultGrid.csv"oFile<<dim<<"维舒尔特方格"<<endl;	for(i=0;i<num;i++){oFile<<b[i]<<",";if((i+1)%dim==0){oFile<<endl;}	}oFile.close();cout<<dim<<"维舒尔特方格已生成,请打开ShultGrid1.csv文件查阅"<<endl;return 0;
}

相关文章:

【c++】rand()随机函数的应用(二)——舒尔特方格数字的生成

目录 一、舒尔特方格简介 二、如何生成舒尔特方格 &#xff08;一&#xff09;线性同余法 1、利用线性同余法生成随机数序列的规律 (1) 当a和c选取合适的数时&#xff0c;可以生成周期为m的随机数序列 (2) 种子seed取值也是有周期的 2、利用线性同余法生成5阶舒尔特方格…...

“深入剖析JVM内部机制:探索Java虚拟机的运行原理“

标题&#xff1a;深入剖析JVM内部机制&#xff1a;探索Java虚拟机的运行原理 摘要&#xff1a;本文将深入探讨Java虚拟机&#xff08;JVM&#xff09;的内部机制&#xff0c;包括类加载、内存管理、垃圾回收、即时编译等关键概念和原理&#xff0c;帮助开发者更好地理解JVM的运…...

pandas 新增数据列的几种方式

准备数据 将下面的数据存到csv中 ymd,bWendu,yWendu,tianqi,fengxiang,fengli,aqi,aqiInfo,aqiLevel 2018-01-01,3℃,-6℃,晴~多云,东北风,1-2级,59,良,2 2018-01-02,2℃,-5℃,阴~多云,东北风,1-2级,49,优,1 2018-01-03,2℃,-5℃,多云,北风,1-2级,28,优,1 2018-01-04,0℃,-8℃…...

linux_驱动_iic总线获取si7006温湿度

应用层si7006.c #include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <arpa/inet.h>…...

虚拟机网络图标不见了

有3台虚拟机之前正常运行的&#xff0c;有一天打开虚拟机发现2台虚拟机的网络连接图标不见了&#xff0c;也ping不通另外两台。 解决&#xff1a;在终端执行以下命令&#xff0c;即可ping通 [roothadoop103 ~]# sudo nmcli network off [roothadoop103 ~]# sudo nmcli network…...

CTF:信息泄露.(CTFHub靶场环境)

CTF&#xff1a;信息泄露.&#xff08;CTFHub靶场环境&#xff09; “ 信息泄露 ” 是指网站无意间向用户泄露敏感信息&#xff0c;泄露了有关于其他用户的数据&#xff0c;例如&#xff1a;另一个用户名的财务信息&#xff0c;敏感的商业 或 商业数据 &#xff0c;还有一些有…...

Redis学习总结

Redis学习总结 文章目录 Redis学习总结Radis基本介绍docker的安装基本数据结构通用命令字符型key的层次结构Hash类型Listset sortedset集合redis的java客户端jedis的使用jedis连接池的配置 SpringDataRedis自定义redistemplate的序列化与反序列化方式stringtemplate的使用 redi…...

云原生全栈体系(二)

Kubernetes实战入门 第一章 Kubernetes基础概念 一、是什么 我们急需一个大规模容器编排系统kubernetes具有以下特性&#xff1a; 服务发现和负载均衡 Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器&#xff0c;如果进入容器的流量很大&#xff0c;Kubernetes 可以负…...

C++设计模式之建造者设计模式

C建造者设计模式 什么是建造者设计模式 建造者设计模式是一种创建型设计模式&#xff0c;它是一种将复杂对象的分解为多个独立部分的模式&#xff0c;以便于构建对象的过程可以被抽象出来并独立变化。 该模式有什么优缺点 优点 灵活性&#xff1a;建造者设计模式允许对象的…...

HDFS Erasure coding-纠删码介绍和原理

HDFS Erasure coding-纠删码介绍和原理 三副本策略弊端Erasure Coding&#xff08;EC&#xff09;简介Reed- Solomon&#xff08;RS&#xff09;码 EC架构 三副本策略弊端 为了提供容错能力&#xff0c;hdfs回根据replication factor&#xff08;复制因子&#xff09;在不同的…...

STM32 DHT11

DHT11 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 使用单总线通信 该传感器包括一个电容式感湿元件和一个NTC测温元件&#xff0c;并于一个高性能8位单片机相连&#xff08;模数转换&#xff09;。 DHT11引脚说明 开漏模式下没有输出高电平的能…...

词法分析器

词法分析器 在早期编译1.0时代&#xff0c;我们的目标是完成程序语言到机器语言的翻译&#xff0c;所以重点在编译器前端&#xff0c;于是我们花费大量时间研究词法分析、语法分析、语义分析等内容。如今的本科编译原理课程&#xff0c;基本上也就到这一层面吧。 在编译2.0时…...

【Spring】Spring之启动过程源码解析

概述 我们说的Spring启动&#xff0c;就是构造ApplicationContext对象以及调用refresh()方法的过程。 Spring启动过程主要做了这么几件事情&#xff1a; 构造一个BeanFactory对象解析配置类&#xff0c;得到BeanDefinition&#xff0c;并注册到BeanFactory中 解析ComponentS…...

状态模式(State)

状态模式是一种行为设计模式&#xff0c;允许一个对象在其内部状态改变时改变它的行为&#xff0c;使其看起来修改了自身所属的类。其别名为状态对象(Objects for States)。 State is a behavior design pattern that allows an object to change its behavior when its inter…...

【uniapp】样式合集

1、修改uni-data-checkbox多选框的样式为单选框的样式 我原先是用的单选&#xff0c;但是单选并不支持选中后&#xff0c;再次点击取消选中&#xff1b;所以我改成了多选&#xff0c;然后改变多选样式&#xff0c;让他看起来像单选 在所在使用的页面上修改样式即可 <uni-d…...

【Spring框架】SpringBoot统一功能处理

目录 用户登录权限校验用户登录拦截器排除所有静态资源练习&#xff1a;登录拦截器拦截器实现原理 统一异常处理统一数据返回格式为什么需要统⼀数据返回格式&#xff1f;统⼀数据返回格式的实现 用户登录权限校验 用户登录拦截器 1.自定义拦截器 package com.example.demo.…...

51单片机学习--按键控制流水灯模式定时器时钟

TMOD负责确定T0和T1的工作模式&#xff0c;TCON控制T0和T1的启动或停止计数&#xff0c;同时包含定时器状态 TF1&#xff1a;定时器1溢出标志 TF0&#xff1a;定时器0溢出标志 0~65535 每隔1微秒计数器1&#xff0c;总时间65535微秒&#xff0c;赋上初值64535&#xff0c;则只…...

Django教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MTV的框架模式&#xff0c;即模型M&#xff0c;视图V和模版T。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的&#xff0c;即是CMS&#xff08;内容管理系统&#xf…...

VGG卷积神经网络-笔记

VGG卷积神经网络-笔记 VGG是当前最流行的CNN模型之一&#xff0c; 2014年由Simonyan和Zisserman提出&#xff0c; 其命名来源于论文作者所在的实验室Visual Geometry Group。 测试结果为&#xff1a; 通过运行结果可以发现&#xff0c;在眼疾筛查数据集iChallenge-PM上使用VGG…...

Python爬虫如何实现IP代理池搭建

大家好&#xff0c;作为一名IP代理产品供应商&#xff0c;我知道很多人在使用Python爬虫时遇到了一些麻烦。有时候&#xff0c;我们的爬虫在爬取过程中会被目标网站识别并封禁IP&#xff0c;导致我们的爬取任务受阻。今天我要分享的就是如何搭建一个高效稳定的IP代理池&#xf…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...