- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我一直在调查 int rand()
来自 <stdlib.h>
的函数在 C11 中,当我偶然发现以下 cppreference-example用于滚动六面骰子。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(NULL)); // use current time as seed for random generator
int random_variable = rand();
printf("Random value on [0,%d]: %d\n", RAND_MAX, random_variable);
// roll a 6-sided die 20 times
for (int n=0; n != 20; ++n) {
int x = 7;
while(x > 6)
x = 1 + rand()/((RAND_MAX + 1u)/6); // Note: 1+rand()%6 is biased
printf("%d ", x);
}
}
特别是这部分:
[...]
while(x > 6)
x = 1 + rand()/((RAND_MAX + 1u)/6); // Note: 1+rand()%6 is biased
[...]
问题:
为什么要添加+ 1u
?自 rand()
是[0,RAND_MAX]
我正在猜测那做rand()/(RAND_MAX/6) -> [0,RAND_MAX/(RAND_MAX/6)] -> [0,6]
?和因为它是整数除法 (LARGE/(LARGE+small)) < 1 -> 0
, 添加 1u
给它所需的范围 [0,5]
?
基于上一个问题,假设 [0,5]
, 1 + (rand()/((RAND_MAX+1u)/6))
应该只通过 [1,6]
并且永远不会触发第二个循环?
一直在四处寻找rand()
已返回 float
在某些时候,但是这似乎是对旧代码的巨大破坏?我猜是支票如果您添加 1.0f
就有意义而不是 1u
使它成为一个 float 分配?
试图绕过这个,感觉我可能会失踪某事..
(附:这不是任何安全关键的基础,我只是在探索标准库。 D.s)
最佳答案
代码通过确保 [1, 6] 中的每个可能结果都是来自 rand
的返回值数量完全相同的输出来避免偏差。 .
根据定义,rand
返回 int
值从 0 到 RAND_MAX
.所以有1+RAND_MAX
它可以返回的可能值。如果1+RAND_MAX
不是6的倍数,那么不可能把它分成6个完全相等的整数区间。所以代码将它分成 6 个尽可能大的相等间隔和一个奇数大小的片段间隔。然后结果rand
被映射到这些区间:前六个区间对应结果从1到6,最后一个区间被拒绝,代码重试。
当我们划分1+RAND_MAX
到 6,有一些商 q 和一些余数 r。现在考虑 rand() / q
的结果:
rand
在 [0, q−1] 中生成一个数字,rand() / q
将为 0。rand
在 [q, 2q−1], rand() / q
中产生一个数将为 1。rand
在 [2q, 3q−1], rand() / q
中产生一个数将是 2。rand
在 [3q, 4q−1], rand() / q
中产生一个数将是 3。rand
在 [4q, 5q−1], rand() / q
中产生一个数将是 4。rand
在 [5q, 6q−1], rand() / q
中产生一个数将是 5。rand
产生一个大于或等于 6q 的数字,rand() / q
将是 6。请注意,在前六个间隔中的每个间隔中,恰好有 q 个数字。在第七区间,可能的返回值在[6q, RAND_MAX
].该间隔包含 r 个数字。
此代码通过拒绝最后一个间隔来工作:
int x = 7;
while(x > 6)
x = 1 + rand()/((RAND_MAX + 1u)/6);
每当rand
在最后一个片段间隔中产生一个数字,此代码拒绝它并重试。当rand
在整个间隔之一中产生一个数字,此代码接受它并退出(在添加 1 之后 x
中的结果是 1 到 6 而不是 0 到 5)。
因此,从 1 到 6(含)的每个输出都映射到完全相等数量的 rand
。值(value)观。
这是从 rand
生成均匀分布的最佳方式从某种意义上说,如果我们使用这样的方案,它的拒绝次数最少。1 rand
的范围已被分成六个尽可能大的区间。剩余的零碎区间不能使用,因为余数 r 小于 6,所以 r 未使用的值不能平均分配给 x
的六个所需值.
1 这不一定是使用 rand
的最佳方式总体上在 [1, 6] 中生成随机数。例如,来自单个 rand
用 RAND_MAX
打电话等于32767,我们可以把这个值看作一个从000000到411411的六进制数字。如果它小于400000,我们可以取最后五位,每个数字均匀分布在[0, 5],并加上一个gts我们想要的 [1, 6]。如果在 [400000, 410000) 中,我们可以使用最后四位数字。如果在[410000, 411000),我们可以用最后三个,以此类推。此外,否则会丢弃的信息(例如前导数字)可能会集中在多个 rand
上。调用以增加我们每次调用 rand
获得的平均输出数量.
关于c - <stdlib.h> rand() 示例代码,对大于最大值的不必要检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58322136/
PHP是这样实现随机数生成的吗? 假设我想计算是或否。每次我都有一定的概率百分比(比如:本例中为 0.05%)。 我愿意: $possibilities = 100 / $probabilityPer
我正在尝试将一段代码从 perl 移植到 php。 perl 代码片段是 akamai 的视频点播链接生成脚本的一部分。该脚本根据视频文件的位置/URL 生成种子(对于单个 URL,它始终是不变的)。
我观察到 rand() 库函数在一个循环中只被调用一次时,它几乎总是产生正数。 for (i = 0; i < 100; i++) { printf("%d\n", rand()); } 但是
我每个循环都需要两个随机数,但不能使用前一个循环的随机数。我迷路了,我已经搜索过,但不知道该怎么做。请帮忙!我把我的代码放在下面。因此,我具体需要的是生成存储在 n1 和 n2 中的两个随机数。然后,
在 MySQL 中使用 RAND() 从一个巨大的表中获取单个随机行非常慢: SELECT quote FROM quotes ORDER BY RAND() LIMIT 1 Here is an a
我正在尝试将 matlab 代码移植到 c++ 中,并在 matlab 中找到了 rand 的用法。matlab的rand函数和c++的rand()函数一样吗?如果没有,在 C++ 或 opencv
我正在尝试将 matlab 代码移植到 c++ 中,并在 matlab 中找到了 rand 的用法。matlab的rand函数和c++的rand()函数一样吗?如果没有,在 C++ 或 opencv
我在 golang 和 C 中使用相同的种子,但得到不同的随机数我知道 php 使用 libc rand(),golang 怎么样? //golang: rand.Seed(12345); rand.
我正在开发的游戏中有以下方法: def search if rand(5) == 0 weapon = Weapon.offset(rand(Weapon.count)).fi
我需要在 Python 中从 C++ 实现 rand 和 rands 来重新加密一堆文件。但似乎无法正确处理。 我有一个 exe 可以将文件解密为文本,我还需要源代码,在编辑文件后我需要使用相同的方法
我在每次插入时将 RAND() 值存储在表中,然后运行以下查询以从表中获取随机行。 select id from test where random_value >= RAND() LIMIT 5;
这是一个看似常见的问题,所以我希望我听起来没有多余。但是从 rand() 返回的范围应该在 0 和 RAND_MAX 之间,但是,当我执行一个非常简单的 rand 语句时,我总是在非常小的范围内获得返
Random#rand 和 Kernel#rand 真的有区别吗? 据我所知,他们使用了不同的“C”函数。 最佳答案 它们在使用 Range 调用时表现相同,但在其他几种情况下则不同。 当使用负整数-
我以实现 RSA 为例。几周前,它似乎工作正常。 然而,现在 key 的生成需要很长时间(>10 秒)。我已将范围缩小到以下行: import "crypto/rand" p, _ := rand.P
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 3 年前。 Improve th
我正在使用全文搜索来提取行。 我根据分数 (ORDER BY SCORE) 对行进行排序,然后在前 20 行 (LIMIT 20) 中,我想对结果集进行兰德 (RAND)。 因此,对于任何特定的搜索词
我使用 rand.Intn(n int) 函数交换 slice 内的元素,但每次运行该程序时,输出都是 slice 内相同的随机元素序列。 我在这里缺少什么明显的东西? 最佳答案 来自 documen
Go 有两个随机数包: crypto/rand,它提供了一种获取随机字节的方法 math/rand,它有一个很好的洗牌算法 我想使用 math/rand 中的 Perm 算法,但要为其提供高质量的随机
我有如下查询: select s.name, m.c_id, m.r_stat, m.l_upd, m.desc, c.email from manual m join selling s join
运行以下查询时: SELECT productid FROM product WHERE productid=ROUND(RAND()*(SELECT MAX(productid) FROM prod
我是一名优秀的程序员,十分优秀!