随机数问题

news2025/1/23 4:49:53

  你知道 C++ 中的 rand() 函数是怎么实现的吗?你知道怎么在一维 / 二维 / 三维空间中等可能地随机取点吗?

随机数是一系列看似无规律、无法预测的数字或值的序列,其产生过程具有一定程度的不确定性。在计算机中,真正的绝对随机数是很难获得的,因为计算机本质上是基于确定性的操作。因此,计算机常常使用称为 “伪随机数生成器”(Pseudo-Random Number Generator, PRNG)的算法来生成序列,这些序列表现出一定的随机性特征,但实际上是通过初始值(随机数种子)推演出来的。在一些需要高度随机性和安全性的场合,则会使用硬件随机数生成器,从而确保系统和数据的保密性、完整性和可靠性。

一. 随机数的本质

计算机生成随机数的方法有很多种,常用的有以下几种:

  • 使用 rand() 函数:rand() 函数是 C 语言标准库中的随机数生成函数,本质上是一个伪随机数生成器 (PRNG),使用线性同余法实现:

    /** 线性同余法实现伪随机数生成器
        N[j+1] = (A * N[j] + B) % M
        gcc 中 A = 1103515245, B = 12345, M = 2^31
     */
    unsigned int next = -1;         // 随机数种子
    
    int rand(void){
        if (next == -1) {           // 未指定种子时使用系统时间作为随机数种子
            next = (unsigned int)time(NULL);
        }
        next = (next*1103515245+12345)%2147483648;
        return (unsigned int)(next);
    }
    
    void srand(unsigned int seed){  // 修改随机数种子
        next = seed;
    }
    

    其中 next 为随机数种子,在程序的一次执行中不断迭代,后一次调用使用前一次生成的随机数作为种子代入线性同余法公式计算得到随机数。srand() 函数可以指定初始的随机数种子,或在程序执行过程中修改随机数种子。当初始随机数种子未被指定时,使用系统时间作为随机数种子。由于 rand() 函数是一个伪随机数生成器,因此只要设定的初始随机数种子相同,生成的随机数序列也是一样的;

  • 硬件随机数生成器 (HRNG):利用物理过程中的不确定性来生成真随机数,HRNG依赖于物理过程,理论上是不可预测的。硬件随机数生成器可以利用多种物理现象来获取随机性:

    • 热噪声:热噪声是由电子运动引起的微小涨落,使用电阻器中的热噪声来生成随机数;
    • 放射性衰变:放射性同位素的衰变是一种随机性过程,也可以用来生成真随机数;
    • 光学噪声:使用光学噪声源,如光二极管的光强涨落,来产生随机性;
    • 时钟抖动:基于时钟抖动的生成器利用计算机内部时钟的微小抖动来获取随机性;

二. 一维空间中的随机数

一维空间本质上就是一条线,因为线密度是均匀分布的,所以等可能地随机取点本质上就是生成这一条线段范围内的随机数,没什么难度。

也许读者想问如果是一条曲线该怎么取,其实曲线的本质是二维空间中宽度为零的图形,并不该在一维中讨论。并且曲线的随机需要更高级的数值技术,此处不作讨论。

三. 二维空间中的随机数

二维空间本质上是一个均匀分布的平面,我们讨论一块封闭的平面。若平面是一个标准的矩形,只需要在 x 和 y 的范围内各自生成随机数即可;若平面是一个圆,阁下该如何应对呢?

这是经典的错误答案:

  在半径为 1 的圆内等概率地取点,可以使用极坐标方式生成随机点。这个方法可以确保在圆内的每个区域有相同的概率被选中。下面是一种常见的方法:
(1)生成一个随机角度:从 0 到 2π 之间随机选择一个角度,表示极坐标系中的角度。
(2)生成一个随机半径:从 0 到 1 之间随机选择一个值,表示极坐标系中的半径。这会覆盖圆的整个范围。
(3)将极坐标转换为直角坐标:使用所选的角度和半径,将极坐标转换为平面上的直角坐标。
这样,你就获得了圆内的一个等概率随机点。

因为极坐标在生成随机半径时所有长度是等可能的,因此 P ( 0 < r < a ) = P ( a < r < 2 a ) P(0 < r < a) = P(a < r < 2a) P(0<r<a)=P(a<r<2a),其中 0 < a < R / 2 0 < a < R/2 0<a<R/2,于是有 P ( S 1 ) / P ( S 2 ) = 1 / 2 P(S1) / P(S2) = 1 / 2 P(S1)/P(S2)=1/2
在这里插入图片描述
但根据古典概型, P ( S 1 ) / P ( S 2 ) = π a 2 / 4 π a 2 P(S1) / P(S2) = \pi a^2 / 4 \pi a^2 P(S1)/P(S2)=πa2/4πa2,与之矛盾,因此这种取点法并不是等可能的。

要想等可能地在圆中取点,最简单直接的办法就是在 x 和 y 的范围内各自生成随机数,若该点在圆的范围内则保留,否则舍弃。但该方法会造成很多无谓的操作,下面介绍 “极坐标投影法”:
(1)生成两个随机数 u u u v v v,范围都是 [0, 1];
(2)计算 θ = 2 π ∗ u \theta = 2\pi * u θ=2πu,这是极坐标的角度;
(3)计算 r = v r = \sqrt v r=v ,这是极坐标的半径;
(4)将极坐标转换为直角坐标: x = r cos ⁡ θ x = r \cos \theta x=rcosθ y = r sin ⁡ θ y = r \sin \theta y=rsinθ

v v v 取平方根是因为在极坐标投影法中,希望生成的点在圆内均匀分布,而不是在整个极坐标平面上均匀分布。如果直接使用 v v v 作为半径,会导致在圆心附近的点聚集,而远离圆心的点分布稀疏。通过对 v v v 取平方根,可以确保半径的分布更加均匀。这是因为在 [0, 1] 区间内,取平方根后的值越接近 1,密度越高,越接近 0,密度越低。这就保证了生成的半径在 [0, 1] 区间内均匀分布,而不是线性分布。

四. 三维空间中的随机数

三维空间就是一个空间,若想在球中等可能随机取一个点,可以仿照极坐标投影法,过程如下:
(1)生成三个随机数 u u u v v v t t t,范围都是 [0, 1];
(2)计算 θ = 2 π ∗ u \theta = 2\pi * u θ=2πu,这是极角,即点坐标与 z z z 轴之间的夹角;
(3)计算 ϕ = 2 π ∗ v \phi = 2\pi * v ϕ=2πv,这是方位角,即点坐标在 xOy 平面的投影与 x x x 轴之间的夹角;
(4)计算 r = t 3 r = \sqrt [3] {t} r=3t ,这是极坐标的半径;
(5)将极坐标转换为直角坐标: x = r sin ⁡ θ cos ⁡ ϕ x = r \sin \theta \cos \phi x=rsinθcosϕ y = r sin ⁡ θ sin ⁡ ϕ y = r \sin \theta \sin \phi y=rsinθsinϕ z = r cos ⁡ θ z = r \cos \theta z=rcosθ

若想在球 上等可能随机取一个点,该怎么做呢?
  球面上的点关于 θ \theta θ ϕ \phi ϕ 都是等可能的,因此可以直接对 θ \theta θ ϕ \phi ϕ 线性随机即可:
(1)生成两个随机数 u u u v v v,范围都是 [0, 1];
(2)计算 θ = 2 π ∗ u \theta = 2\pi * u θ=2πu,这是极角;
(3)计算 ϕ = 2 π ∗ v \phi = 2\pi * v ϕ=2πv,这是方位角;
(4)将极坐标转换为直角坐标: x = sin ⁡ θ cos ⁡ ϕ x = \sin \theta \cos \phi x=sinθcosϕ y = sin ⁡ θ sin ⁡ ϕ y = \sin \theta \sin \phi y=sinθsinϕ z = cos ⁡ θ z = \cos \theta z=cosθ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1006980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

当你的公司突然开始大量的裁员,被留下的你,真的准备好面对以后了吗?

留下来的&#xff0c;也是迷茫的 最近公司突然开始大量裁员&#xff0c;裁了一多半&#xff0c;作为唯一留下的APP 端开发人员&#xff0c;也开始陷入了焦虑&#xff0c;开始了思考&#xff0c;未来究竟何去何从&#xff0c;是否再去转到原生&#xff0c;从事原生的开发工作&a…

元服务那些事儿 | 挥剑解决隐私声明,激发开发豪情

话说元服务初上的年间&#xff0c;鸿蒙江湖高手云起&#xff0c;都是一顿键盘手猛敲&#xff0c;元服务推陈出新&#xff0c;创意层出不穷&#xff0c;无不风生水起。 江湖规矩&#xff1a;每个元服务必须提供规范的隐私声明&#xff0c;否则提交元服务发布上架后&#xff0c;将…

AI 为我制作了 5 份简历,过程太美好了

现在&#xff0c;每个人都在使用人工智能 (AI) 来让自己的生活变得更轻松——从订购杂货、找到丢失的钥匙到撰写完美的简历。人工智能简历生成器是令人惊叹的工具&#xff0c;但选择合适的工具可能是一项挑战。 人工智能简历写作工具的市场正在迅速扩大&#xff0c;并且越来越…

【Linux环境】编译器 gcc/g++的使用

​&#x1f47b;内容专栏&#xff1a; Linux操作系统基础 &#x1f428;本文概括&#xff1a; 预处理、编译、汇编、链接、动静态库、gcc选项等。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.9.13 背景知识 预处理&#xff08;进行宏替换…

element-ui文件下载(单个)

1. 单个附件下载 <el-buttontype"text"size"small"click.native.prevent"download(scope.row)" >下载</el-button>export default {data() {return {downloadUrl: http://127.0.0.1:8881/XX/XX, // 下载接口}},methods: {download(…

骨传导耳机怎么听到声音?骨传导耳机是否会对听力造成损害?

其实骨传导耳机让我们听到的的传声原理很简单&#xff0c;而且骨传导现象很常见&#xff0c;简单的来说&#xff0c;就是像我们平时吃薯片或者挠头发&#xff0c;无论声音再小&#xff0c;自己也能听见&#xff0c;这就是骨传导的现象&#xff0c;也是为啥骨传导耳机不需要入耳…

【SpringMVC】JSON注解异常处理的使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Spring MVC》。&#x1f3…

【Axure高保真原型】日历日期原型模板

今天和大家分享日历日期的原型模板&#xff0c;包括月计划、周计划、日计划的原型案例&#xff0c;以及日期、时间、月份、区间选择器……具体效果可以点击下方视频观看 【原型预览及下载地址】 Axure 原型 备用地址&#xff1a;Untitled Document 【原型效果】 【原型效果…

ABAP 获取信贷超额函数

业务需求&#xff1a;在创建销售订单时&#xff0c;信贷超额不会影响单据正常生成&#xff0c;前台信贷超额消息时前台弹框式警告&#xff0c;故而不会在BAPI RETURN中返回&#xff0c;也许需要获取这类消息&#xff0c;返回给外围系统。 函数&#xff1a;SD_DELIVERY_CREDIT_C…

利用面向对象方法,处理数据文件【Python】

题目背景&#xff1a;处理两份数据文件&#xff08;文本数据和JSON数据&#xff09;&#xff0c;用面向对象的方法&#xff0c;效果图用柱状图呈现。 本题思路&#xff1a; 1.首先&#xff0c;创建一个【基础数据类】&#xff0c;名为Record&#xff0c;它将包含成员属性和成员…

【数据结构-堆】堆

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

嵌入式行业这个领域是否值得坚持

今日话题&#xff0c;嵌入式行业&#xff0c;特别是对于嵌入式新人&#xff0c;是否值得坚持这个领域&#xff1f;对于想要进入嵌入式行业的人来说&#xff0c;坚持是明智的选择。这个领域涉及硬件和软件&#xff0c;技术更新较慢&#xff0c;但它也为你提供了积累经验的机会。…

mysql学习查缺补漏1---基础部分(小滴课堂)

举例&#xff1a; DDL&#xff1a;建库&#xff0c;建表。 DML&#xff1a;对表的数据进行增删改操作。 DQL&#xff1a;对数据进行查询。 DCL&#xff1a;对用户的权限进行设置。 create table teacher as select * from student where 12; 该条语句只用于复制表结构&…

Kubernetes 使用configmap挂载卷给Pod内的nginx容器

目录 实验&#xff1a;使用configmap挂载卷给Pod内的nginx容器 1、创建nginx.conf配置文件&#xff08;必须由nginx镜像里的nginx.conf修改而来&#xff0c;防止出现配置不相似的情况出现&#xff0c;导致访问不了nginx网页&#xff09; 2、通过nginx.conf文件创建configmap容…

Java 代理模式之静态代理与动态代理

1&#xff0c;代理模式 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。 代理模式的目的&#xff1a; &#xff08;1&#xff09;通过引入代理对象的方式来间接访问目标对象&#xff0c;防…

对话式人工智能(Conversational AI):提高模型的智能程度和扩展能力

对话式人工智能的趋势与挑战 对话式人工智能 (AI) 已经出现在许多家庭的客厅、汽车和在线购物体验中。聊天机器人、语音助手、智能扬声器、交互式语音识别系统&#xff1a;所有这些都是对话式 AI 的示例。由于该领域通过增强的客户体验提供了更多可访问性&#xff0c;因此吸引…

PHP自己的框架2.0结合容器技术(重构篇二)

目录 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 3、框架使用容器类来执行public/index.php 4、运行效果还是一样 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 什么是容器&#xff1f;容器就相当于盒子&#xff0c;把很多类放里…

录音怎么转换成mp3格式?支持二十多种格式

录音怎么转换成mp3格式&#xff1f;在我们的日常生活和工作中&#xff0c;录音是一项非常有用的工具&#xff0c;随着手机以及录音设备越来越普及化&#xff0c;让录音这件事情变得非常的简单&#xff0c;录音可以帮助我们解决非常多的事情。例如通过录音&#xff0c;我们可以记…

Linux C++ OpenVINO 物体检测 Demo

目录 main.cpp #include <iostream> #include <string> #include <vector> #include <openvino/openvino.hpp> #include <opencv2/opencv.hpp> #include <dirent.h> #include <stdio.h> #include <time.h> #include …

OJ练习第171题——复制带随机指针的链表

复制带随机指针的链表 力扣链接&#xff1a;138. 复制带随机指针的链表 题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个…