一文详解编程中的随机数

随机数,相信大家都不陌生,网上有很多生成随机数的小工具。直观来看,随机数就是一串杂乱无章的数字、字母、以及符号的组合, 比如pSTkKIiZMOlDxOgwpIQGdlZwrJCRiHRK。但随机数真的就随机吗?真的就无法预测吗?什么场景下可以用什么方式来生成随机数呢? 这篇文章将为大家介绍随机数的类型,在程序中如何使用随机数,以及随机数在密码学中使用场景。希望能尽量地将在开发过程中需要用到的随机数知识都收纳在这里,方便大家进行查阅!

随机数的类型

在知乎上看到过一个说法,认为这个世界没有真正意义上的随机,比如扔骰子。如果能算对扔出时的转速、方向,并测出空气中的阻力,桌面的阻尼系数,骰子的质量 等等因素,那么就有机会算出骰子落地时的点数。我猜想赌神大概率也是基于这种原理吧。物理科学上是有“真正”意义的随机的,那就是量子力学的不可测原理。它是由德国著名物理学家海森堡在1927年发表的论文《论量子理论运动学与力学的物理内涵》中提出来的。不是特别理解其中的内容,但是从字面上简单的理解,就是对于微观粒子,它的速度和位置不能准确测量,当对其中一个物理量测量得越准确时,另一个物理量就越模糊。

从编程角度看,我们的随机数生成器分为两种大类型,一种是真随机数生成器,一种是伪随机数生成器。

真随机数生成器 TRNG - True Random Number Generator

前面说了实际上基本没有真正意义随机,那程序和算法本身就更加不能产生真随机,但是我们可以想办法迂回地产生统计意义上的真随机。比如Linux内核的随机数发生器: Linux维持一个熵池,不断地收集非确定性的事件,比如时钟,鼠标的移动,键盘的敲击, IO的响应时间,磁盘的速度,wifi的强弱,内存的变化等等,然后基于一定的算法给出一个数。

伪随机数生成器 PRNG - Pseudo Random Number Genrator

如果需要快速生成大量的随机数,那么真随机数生成器可能由于收集不到那么多的随机事件而产生阻塞行为。在不需要那么高安全级别的随机数需求下,我们可以采用伪随机数生成器来生成随机数。伪随机数生成器一般是基于一个给定的初始值,也就是种子 - seed,用一定的算法来算出一个数。且算法内部维持一个内部状态,每次生成一个新的随机数,这个值都会跟着变化,这样就能产生不一样的随机数来。常见的伪随机数生成器的算法有:

  • 线性同余法 - Linear Congruential Generator (简称LCG)
  • 马特赛特旋转演算法 - Mersenne Twister.

Java中的Random() 用的就是线性同余法。线性同余方法是目前应用广泛的伪随机数生成算法,其基本思想是通过对前一个数进行线性运算并取模从而得到下一个数,递归公式为:

在这里插入图片描述

其中A,B,M是产生器所用到的常量

随机数的使用

真随机数

我们可以通过下面这个命令得到操作系统内核提供的外部熵随机数生成器:

λ head -c 32 /dev/random | openssl enc -base64
zLvAZ2vfFTUQ+ENPLdbG2F8B3wv86LM9X2s3DeymN28=

这个命令将会从Linux内核的熵池中读取一个32位的随机数,并用64进制展示出来。我们也可以选择用数字的形式展示出来:

λ cat /dev/random| tr -dc '0-9' | fold -w 10| head -n 4
0231488700
4599846604
7629411051
4199097655

上面这个命令从熵池中4个10位的随机数,并用0-9展示出来。

但用这个命令的时候要小心,由于熵池中的值通过记录系统的随机事件得来的,那么就有可能有用完的时候,那么这时这个命令就会阻塞在这里,直到有系统随机事件进到熵池中才会继续。这样对程序来说不是很友好,于是操作系统的随机数生成器一般都提供另外一个工具,在熵池的随机事件用完之后,能用伪随机算法产生一个随机数给你:

λ cat /dev/urandom| tr -dc 'a-zA-Z0-9' | fold -w 10| head -n 4
EK0Z3g49By
csziDZeWtO
EhHu30IcM4
PyDyY47Ah5

Golang的内置随机数生成器rand就是基于 /dec/urandom来实现的。

开发中常见的随机数生成器

这里我们以Java语言为例,介绍一下常见的随机数生成器的用法。

  • Random()

首先一起来看一下这个最常见的Random. Random实现了基于线性同余法的伪随机数生成器,其构造函数接收作为种子的参数seed,如果不给定seed,则默认采用当前时间戳作为种子。 下面的函数可以生成指定位数的随机字母串:

public static String ALPHA = "abcdefghijkllmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";   
public static String generate_alphabetic_using_Random(int length) {
   
        Random random = new Random();
        StringBuffer buffer = new StringBuffer();
        int bound 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值