我需要在 C 中生成随机数 [重复]
Posted
技术标签:
【中文标题】我需要在 C 中生成随机数 [重复]【英文标题】:I need to generate random numbers in C [duplicate] 【发布时间】:2010-11-14 12:30:45 【问题描述】:可能的重复:How to generate a random number in C?implementation of rand()Generating random terrain in Blender3D
我需要 C 语言中的高质量随机数,但我不知道该怎么做。我需要能够获得 1-100 的数字。任何帮助,或者指出我可以找到帮助的地方。
【问题讨论】:
这个时候总有人说“定义高品质”,那还不如说是我呢。 你在哪个平台上工作。有基本的 rand(),但每个操作系统都有更好的生成随机数的方法。如果您指定平台,每个人都会更容易。 它至少应该随机出现,最多运行 1 亿次。 去无线电小屋。购买一个二极管、一个 NTR 电阻、一个电容器和串行电缆。切断不适合您的计算机的串行电缆的一端。将二极管和电阻串联焊接在电缆的引脚 DTR 和 DSR 之间。在 DSR 和 TXD 引脚之间焊接电容。编写一个小的 C 程序来执行以下操作: 将 DTR 设置为 1。启动计时器。监控 DSR,直到它变为 1。停止计时器。从经过的时间计算阻力。从该值中检索多个位以用作随机数的一部分。重复直到积累了足够多的位。现在,你可以下注和(模数)100... 不是重复的 IMO。这些其他问题都没有提到这里要求输出与随机无法区分。现在,当然,您可以确切地争论这意味着什么,但是无论您做出什么决定,该决定都会影响问题的答案。这些其他问题都不需要安全的 RNG,也没有一个像样的答案如何将值缩放到 1-100 范围内。 【参考方案1】:你可以试试这样的:
main()
srand(time(0));
for(int i=0;i<1000;++i)
printf("%f ", ((float)rand())/RAND_MAX*99+1);
return 0;
这是标准 rand() 所能提供的均匀分布。
【讨论】:
我不认为这“随机出现多达 1 亿次”。例如,在 Windows 上,RAND_MAX 为 32767。因此,一旦此代码被修复为有时不输出 101,值 2、3、5、6... 比值 1、4、7... 大约多 0.3%。 . 我认为在 100M 样本中,偏差应该非常明显,甚至假设 rand() 在这么多样本中与随机无法区分。几乎可以肯定不是,尽管我不能立即进行区分测试。 正如我所说,它与 rand() 一样随机。那里还有其他具有更好“随机性”的rng(例如Mersenne twister)。你确定偶数的概率略很重要吗?我将其全部划分为 [0,1] 区间并将其乘回到 [1,100]。 我什么都不确定;-) 但是在评论中,OP 说它应该与随机样本和 100M 样本无法区分。如果这是真的,那么 0.3% 的偏差很重要。 rand() 可以返回 32768 个不同的值,我们希望将其映射到 100 个输出。因此,无论随机性的来源是什么,68 个输出将比其他 32 个输出多 0.3%,除非您对从(RAND_MAX - RAND_MAX % 100)
到 RAND_MAX
的结果采取标准预防措施。 /跨度>
抱歉,这是您使用模数时的预防措施。重新缩放时并不那么简单。
重新缩放为浮点数或双精度数使浮点表示的怪癖发挥作用。当你放大时,你会在“箱子”的边缘得到奇怪的锯齿。【参考方案2】:
http://mathworld.wolfram.com/RandomNumber.html
本文介绍了创建您自己的随机数生成器的基础知识,如果您发现它缺乏分发,它的性能将优于标准 C 库函数。它产生更好的传播,因此产生更多的随机数。
如果您希望生成无法逆向工程的东西(例如扑克网站),这一点至关重要。
【讨论】:
正是我需要的。谢谢。 那里有很多好的、调试良好的 PRNG,使用起来毫无意义。这是为了学习。 在滚动您自己的 RNG 时要非常小心,这很容易出错,但很难证明它是错误的。 是的,不要这样做。在这方面比你或我做得更好的人已经这样做了。 ***.com/questions/1046714/…【参考方案3】:这是在 C 中产生均匀分布随机数的最简单方法:
第 1 步。确保包含标准库头文件以获取必要的函数原型
#include <stdlib.h>
第 2 步。 使用 srand()
播种随机数生成器。种子决定了随机数从哪里开始。对于给定的种子,随机数序列将始终完全相同。这使您可以获得随机但可重复的结果。如果您不需要它是可重现的,最好使用当前时间作为种子,这样每次运行的随机序列都会不同。
srand(time(NULL));
(如果这样做,请务必包含 time.h)。此外,每个程序运行只为生成器播种一次,除非您要生成大量(数百万或数十亿)随机数。频繁播种会使序列更少随机。
第 3 步。 获取您的随机数。
rand()
此函数返回一个介于 0 和 RAND_MAX 之间的随机数,这是一个定义为相当大整数的宏。
第 4 步。 将您的随机数放入您想要的范围内。这样做的一般公式是这样的:
int random_number = rand() % range + min;
其中 range 是您要从中选择的(连续)个数,min 是其中最小的一个。所以要生成一个介于 1 和 100 之间的数字,范围是 100,最小值是 1:
int random_number = rand() % 100 + 1;
有些人反对这个公式,因为它使用 rand() 给出的数字的低位,并且在软件伪随机数生成器的旧实现中,这些通常比高位随机性要小,但是任何现代系统,这种方法都应该很好。
【讨论】:
这是一种不好的做法,因为 if 偏爱接近刻度下端的数字。如果 RAND_MAX 是 something20,那么 0-20 之间的所有数字被选中的机会都会增加。这是一个小小的支持,因为 RAND_MAX 是一个非常大的数字,但仍然存在。 ::shrugs:: 对于可以接受“rand()”的应用程序,来自模数的偏差是微不足道的。如果需要,您始终可以编写一个包装器来剪辑违规投掷并重试。 -1:将 % 与 rand 一起使用非常糟糕。在 [1, 100] 中生成 10,000 个随机数,您会看到非常明显的偏差。 (考虑 RAND_MAX = 100 的情况,在这种情况下,您掷出 1 的可能性是任何其他数字的两倍。)【参考方案4】:标准 C 库有 rand 可能就足够了,除非您需要具有特定统计分布的 prng..
【讨论】:
【参考方案5】:“公平分配”是指您对rand()
并不满意。在这种情况下,您可能应该使用特定于操作系统的方法来生成加密安全的随机数 - 在 Unix 上是 /dev/random
或 /dev/urandom
(取决于您的需要),在 Win32 上是 CryptGenRandom
或 RtlGetRandom
。特别是在 Win32 上,如果你使用的是 VS2005 或更高版本,你可以只使用rand_s
。
【讨论】:
+1 用于使用其他人创建的知名库。没有更好的方法来使用加密保护任何东西。 同意需要一个由花费大量时间思考和测试问题的人编写的优秀库。但我总是对使用其中一种方法的好处是否不会被不当调用而否定。 我想,如果您不正确地调用该库,那么您很有可能自己不正确地实现它,甚至更多。 是的,但至少如果您自己编写,您肯定会知道它被搞砸了。 :-)【参考方案6】:其他帖子有很好的建议。如果您真的想深入了解随机数生成的内容,请查看Numerical Recipes in C。以Chapter 7开头。
【讨论】:
【参考方案7】:作为高质量的随机数生成器,请不要使用rand()
,或非质量保证代码。错误地生成随机数非常容易(查看 Knuth 在“计算机编程的艺术:半数值算法”中的有趣故事)。最简单的方法可能是使用the generators in GNU's scientific library。它一键安装*nux,GSL有几个端口到Windows。我用过。它易于调用且运行良好。
【讨论】:
【参考方案8】:如果你真的需要彩票质量的随机数,我认为你根本不需要数字算法。
You want an actual physical process. See Random.org.你愿意付钱吗?
如果您真的需要随机数,请注意程序化随机数生成器。正如我们目前在答案中看到的那样,不仅很难编写一个好的 random(),而且很难弄清楚如何正确使用它的输出,无论是通过模还是通过缩放。即使是人们认为“显而易见”的代码也常常被证明是不正确的。
将整数转换为浮点数或双精度数只会带来浮点数的所有怪癖(例如它们能够表示更多接近零的数字而不是接近一的数字)。
您有什么要求?您的号码需要经过认证吗?还是您只是想要真正好的随机数?您将使用哪些测试来查看您的随机生成器是否“好”?
【讨论】:
在宏观层面上,我希望分布均匀,每个数字出现大约 1% 的时间。但在微观层面上,我想要一个高波动性,其中 100+ 百万个随机数的任何部分看起来都是完全随机的。 有衡量这些东西的指标,但要意识到人类在识别随机性方面是出了名的差,所以当你说“出现”时,你的意思是你更关心随机性的外观而不是它有以真正随机的方式生成?换句话说,真正的随机数比人们预期的要“条纹”。你能忍受真正的条纹还是宁愿它在观察者看来是随机的? 您浏览过***中列出的工具吗? en.wikipedia.org/wiki/Randomness_tests以上是关于我需要在 C 中生成随机数 [重复]的主要内容,如果未能解决你的问题,请参考以下文章