随机数:真随机数和伪随机数一样吗_rdrand真随机数

随机数:真随机数和伪随机数一样吗_rdrand真随机数说到随机这个词,相信各位肯定都深有体会了。生活中有太多的不确定因素从各方各面影响着我们,但也正是因为这样我们的人生更加多彩,具有了更多的可能性。可以说,随机是个非常有魅力的东西。而游戏开发者通常也会利用随机让游戏更加的吸引人。例如你正在玩的手机游戏里面的抽卡系统就是很好的例子。笔者曾经在阴阳师的抽符大坑中痛苦不堪。什么,你只玩王者荣耀?那里面的抽英雄抽符文,我想你应该也经历过绝望吧。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

说到随机这个词,相信各位肯定都深有体会了。生活中有太多的不确定因素从各方各面影响着我们,但也正是因为这样我们的人生更加多彩,具有了更多的可能性。

可以说,随机是个非常有魅力的东西。

你在生活中可能因为随机享过福,也有可能吃过亏。想要对它了解更多?如今是时候去揭开它的真面目了。

I.真随机数&伪随机数的基本定义

在这之前需要先明白一点:随机数都是由随机数生成器(Random Number Generator)生成的。

1.真随机数 TRUE Random Number

真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等,这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。      —-百度百科

根据百科上的定义可以看到,真随机数是依赖于物理随机数生成器的。使用较多的就是电子元件中的噪音等较为高级、复杂的物理过程来生成。

至于“宇宙中不存在真正的随机”这种言论已经属于哲学范畴,在此不做讨论。在此我们默认存在随机。

使用物理性随机数发生器生成的真随机数,可以说是完美再现了生活中的真正的“随机”,也可以称为绝对的公平。

2.伪随机数 Pseudo-Random Number

真正意义上的随机数(或者随机事件)在某次产生过程中是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的,是不可见的。而计算机中的随机函数是按照一定算法模拟产生的,其结果是确定的,是可见的。我们可以这样认为这个可预见的结果其出现的概率是100%。所以用计算机随机函数所产生的“随机数”并不随机,是伪随机数。

—百度百科

从定义我们可以了解到,伪随机数其实是有规律的。只不过这个规律周期比较长,但还是可以预测的。主要原因就是伪随机数是计算机使用算法模拟出来的,这个过程并不涉及到物理过程,所以自然不可能具有真随机数的特性。

II.c语言中的伪随机数详解

既然我们已经了解了真伪随机数的概念,接下来就来探究一下离我们最近的伪随机数吧。

c语言中就存在一个随机函数:rand().它就是一个标准的伪随机数生成器。依赖的头文件是stdlib.h.

接下来我就使用rand函数,来试着产生一些随机数。

#include <stdio.h>
#include <stdlib.h>

int main ()
{
       int random = rand();
    printf("%d\n",random);
    random = rand();
    printf("%d\n",random);
    random = rand();
    printf("%d\n",random);
}

Jetbrains全家桶1年46,售后保障稳定

这里我使用一个整形变量来接受rand函数产生的随机数,并对其进行打印。

随机数:真随机数和伪随机数一样吗_rdrand真随机数

执行后,成功看到了结果。貌似是一串随机数。

可是,当我们多次执行时,发现它的数值却还是41,18467, 6334。

这并不是我们想要的结果,我们希望每一次运行都可以产生不同的数值。可是如何解决这个问题呢?

其实,在c语言中的rand函数中有一个定义叫做种子,rand函数是通过对这个种子进行一系列的运算来模拟出一个随机数的。我们直接调用rand函数,并不指定种子,系统就会调用默认的种子:1,来产生随机数。因为每次重新运行时的种子都是1,运行出来的结果自然就还是这几个数啦。

现在我们已经知道了种子这个重要的参数,我们就可以用一个一元二次方程来模拟这个过程。

例如,rand函数的内部实现为 x^2 + 4x – 8,这个种子就相当于x。

如果想要改变rand最终的值,只能通过改变x来实现。

那么,既然要产生随机数,x就应该是一直在不断变化的,才能让x^2 + 4x – 8这个表达式的值不断的变化。

x,也就是种子,该采用什么东西呢?

没错,最理想的就是时间时间每分每秒都在变动,正好符合我们的要求。这里需要使用到time.h。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main ()
{
	srand ((unsigned)time(NULL));
	int random = rand();
	printf("%d\n",random);
	random = rand();
	printf("%d\n",random);
	random = rand();
	printf("%d\n",random);
}

对之前的代码进行改进。通过时间设置种子的值:srand ((unsigned)time(NULL));

这时候再运行,每次都会得出不同的结果了。

这里srand函数的定义就是:随机数生成器的初始化函数。通常是和rand函数配合使用的。

函数原型:srand(unsigned seed)

代码中的time(NULL)将返回计算机目前的时刻与1970年1月1日0时0分0秒之间的时间差,单位是秒。

srand又需要unsigned int类型,所以这里使用一个强制类型转换,最后完成种子的设置。

需要注意的是,srand函数必须放在循环或者循环调用的外面,否则还是会得出重复的数字。


到这里,就可以产生你想要的随机数了。如果你想在0~4之间产生随机数,只需要int random = rand()%4,这样每次出来的随机数就会在0-4中了。

那么,我想让产生的随机数在1-100范围内,用int random = rand()%100,这样行吗?

当然不行!!


是,没错,结果都是在范围内的。但是你如果短时间内连续执行,会发现它是有规律可循的,会随着时间的推移慢慢上涨,到100后再回到0,再重新上涨…

这可是个严重的问题。游戏如果敢这么做,肯定会亏的妻离子散。

所以,这个办法只能用于范围较小的随机数,应用范围非常窄。

通用的一个方法是  (int)(n*rand()/(RAND_MAX+1.0)),这样产生随机数的周期会大大缩短,从而达到我们想要的效果。

III.真随机数的详解

之前已经介绍过,真随机数是使用物理设备产生的。那么在这里我就要介绍一个网站:

真随机数生成网站

这个网站可以免费提供真随机数的服务,并且可以自己设置上下限,通常用于重要场合。

那么,既然伪随机数生成那么简单,而且看上去确实是随机的,为什么人们还要大费周章的使用繁琐又高价的物理设备去获得随机数呢?

前面在伪随机数的定义里讲了,伪随机数其实是有周期的。

听起来很恐怖对不对?也就是说,经过足够多次的运行,结果会出现重复。

// Requires the GD Library
header("Content-type: image/png");
$im = imagecreatetruecolor(512, 512)
    or die("Cannot Initialize new GD image stream");
$white = imagecolorallocate($im, 255, 255, 255);
for ($y = 0; $y < 512; $y++) {
    for ($x = 0; $x < 512; $x++) {
        if (rand(0, 1)) {
            imagesetpixel($im, $x, $y, $white);
        }
    }
}		
imagepng($im);
imagedestroy($im);

这是摘自

Pseudo-Random Num.vs True Random Num

的一段代码,使用PHP语言编写的。它的作用就是将随机数可视化。下面分别放出真随机数和伪随机数的图像。

真随机数图像:

随机数:真随机数和伪随机数一样吗_rdrand真随机数

伪随机数图像:

随机数:真随机数和伪随机数一样吗_rdrand真随机数

很明显的可以看到,伪随机数的图像呈现出了某种规律。但作者也同时解释到:这个现象也只是在Windows平台上的php语言中的 rand函数里出现。当他在linux上运行同样的代码时,发现并没有非常明显的规律。同样是windows平台的PHP语言,使用mt_rand()这个改进了的随机数生成函数的话也不会发现明显的规律。

笔者推测是大大增加了重复的周期,毕竟是算法产生的伪随机数,永远不可能具有真随机数的不确定性。也就是说,规律还是存在,只不过需要更长的观察周期 才能够发现而已。

所以真随机数的重要性就在于,完全没有规律。所以一般企业对产品的加密秘钥的生成必须采用真随机数生成器,这样才能保证万无一失,杜绝了被激活成功教程的可能性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/201126.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mybatisplus关联表查询_hibernate多表查询

    mybatisplus关联表查询_hibernate多表查询我们在设计表的时候往往一个表的外键作为另一张表的主键,那么我们在查询的时候就要查询两个表的数据。下面来说下实现的方法。数据库表的结构wc_user实体类publicclassWcUserimplementsSerializable{ //用户idprivateStringuserId;//用户密码privateStringus…

    2022年9月14日
    0
  • MySQL数据库使用命令行备份|MySQL数据库备份命令

    MySQL数据库使用命令行备份|MySQL数据库备份命令转至  神马和浮云 ,命令未测试,主要是方便操作mysql时需要而记的笔记  例如:数据库地址:127.0.0.1数据库用户名:root数据库密码:pass数据库名称:myweb 备份数据库到D盘跟目录mysqldump-h127.0.0.1-uroot-ppassmyweb&gt;d:/backupfile.sql备份到当前目录备份MySQ…

    2022年6月10日
    31
  • 微信小程序 40029错误

    微信小程序 40029错误{“errmsg”:“invalidcode,hints:[req_id:xxxxxxx],“errcode”:40029”}查看project.config.json中的appid是否与自己申请的appid一致。不一致就会出现这种问题。解决方法就是改成自己申请的appid…

    2022年4月28日
    44
  • 基于51单片机的多功能八路抢答器[通俗易懂]

    基于51单片机的多功能八路抢答器[通俗易懂]1.功能介绍多功能八路抢答器是基于51单片机来设计的,除了可以实现最基本功能——8路抢答外,还具有自动处理犯规选手,抢答时间调整,还可以进行答题,计分,并且可以查询或修改分数。2.硬件设计该抢答器的硬件由五个部分组成,包括单片机、按键电路、数码管显示电路、指示灯电路和声音提示电路。硬件框图如下(2)硬件原理图由于每个部分的硬件电路都比较简单,就不做介绍了,大家直接看图。3.软件设…

    2022年10月20日
    0
  • 七年级小四门知识点_unity animator trigger

    七年级小四门知识点_unity animator triggerUnity小科普老规矩,先介绍一下Unity的科普小知识:Unity是实时3D互动内容创作和运营平台。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助Unity将创意变成现实。Unity平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。也可以简单把Unity理解为一个游戏引擎,可以用来专业制作游戏!Unity小知识点学习Unity中使用代码查询D.

    2022年9月19日
    0
  • 操作系统用户态和内核态之间的切换过程是什么_用户进程从用户态切换到内核态

    操作系统用户态和内核态之间的切换过程是什么_用户进程从用户态切换到内核态操作系统用户态和内核态之间的切换过程1.用户态和内核态的概念区别究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子:1)例子voidtestfork(){if(0==fork())…

    2022年9月17日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号