我需要使用C生成随机64位无符号整数。我的意思是,范围应该是0
到18446744073709551615
。RAND_MAX
是1073741823
。
我在链接中发现了一些解决方案,这些解决方案可能是重复的,但答案大多连接了一些rand()
结果或进行一些增量算术运算。因此,结果始终是 18 位或 20 位数字。我还想要像5
,11
,33387
这样的结果,而不仅仅是3771778641802345472
。
顺便说一句,我真的没有太多的C经验,但任何方法,代码示例和想法都是有益的。
如果您有足够好的随机字节源(例如,linux机器上的/dev/random或/dev/urandom),那么您可以简单地从该源中消费8个字节并将它们连接起来。如果它们是独立的并且具有线性分布,那么就设置好了。
如果你不这样做,你也可以这样做,但是在你的伪随机生成器中可能有一些人工制品,这些人工制品会给各种各样的厄运带来阻碍。
示例代码假设我们有一个开放的二进制< code >文件*源代码:
/* Implementation #1, slightly more elegant than looping yourself */
uint64_t 64bitrandom()
{
uint64_t rv;
size_t count;
do {
count = fread(&rv, sizeof(rv), 1, source);
} while (count != 1);
return rv;
}
/* Implementation #2 */
uint64_t 64bitrandom()
{
uint64_t rv = 0;
int c;
for (i=0; i < sizeof(rv); i++) {
do {
c = fgetc(source)
} while (c < 0);
rv = (rv << 8) | (c & 0xff);
}
return rv;
}
如果您将“从随机性设备读取随机字节”替换为“从函数调用中获取字节”,您所要做的就是调整方法#2中的变化。
你更有可能得到一个“多位数”的数字,而不是一个“少位数”的数字(在0到2 ** 64之间的所有数字中,大约95%有19位或更多的十进制数字,所以这实际上是你最可能得到的。
如果您不需要加密安全的伪随机数,我建议您使用MT19937-64。它是梅森·费尔托斯特PRNG的64位版本。
请不要组合rand()
输出,也不要使用其他技巧。使用现有实现:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
关于“结果总是18位数或20位数。”
见@托马斯评论。如果你生成的随机数足够长,代码会生成像5、11和33387这样的数字。如果代码每秒生成1,000,000,000个数字,作为非常小的数字可能需要一年的时间
rand()
简单返回随机位。一个简单的方法一次拉取 1 位
uint64_t rand_uint64_slow(void) {
uint64_t r = 0;
for (int i=0; i<64; i++) {
r = r*2 + rand()%2;
}
return r;
}
假设RAND_MAX
是2-1的幂,如OP的情况1073741823==0x3FFFFFFF<罢工>30每次至少生成15位。以下代码将调用
rand()
5<罢工>3.
次-有点浪费。相反,移出的位可以保存为下一个随机数,但这会带来其他问题。把它留到另一天吧。
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=0; i<64; i += 15 /*30*/) {
r = r*((uint64_t)RAND_MAX + 1) + rand();
}
return r;
}
便携式循环计数方法避免了
15 /*30*/
- 但请参阅下面的 2020 编辑。
#if RAND_MAX/256 >= 0xFFFFFFFFFFFFFF
#define LOOP_COUNT 1
#elif RAND_MAX/256 >= 0xFFFFFF
#define LOOP_COUNT 2
#elif RAND_MAX/256 >= 0x3FFFF
#define LOOP_COUNT 3
#elif RAND_MAX/256 >= 0x1FF
#define LOOP_COUNT 4
#else
#define LOOP_COUNT 5
#endif
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=LOOP_COUNT; i > 0; i--) {
r = r*(RAND_MAX + (uint64_t)1) + rand();
}
return r;
}
这里评论的自相关效应是由弱的< code>rand()
引起的。c #没有指定随机数生成的特定方法。以上依赖于< code>rand() -或任何使用的基本随机函数-是好的。
如果rand()
低于标准,那么代码应该使用其他生成器。然而,人们仍然可以使用这种方法来构建更大的随机数。
[编辑2020]
当RAND_MAX是梅森数时,哈尔瓦德·弗鲁斯提供了确定RAND_MAX
位数的好方法 - 2减去1的幂。
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
_Static_assert((RAND_MAX & (RAND_MAX + 1u)) == 0, "RAND_MAX not a Mersenne number");
uint64_t rand64(void) {
uint64_t r = 0;
for (int i = 0; i < 64; i += RAND_MAX_WIDTH) {
r <<= RAND_MAX_WIDTH;
r ^= (unsigned) rand();
}
return r;
}
我想用骰子做一个游戏,我需要在其中加入随机数(以模拟骰子的侧面。我知道如何在1到6之间进行)。使用 不能很好地工作,因为当我运行程序几次时,我得到的输出是: 所以我想要一个每次都会生成不同随机数的命令,而不是连续5次生成相同的随机数。是否有命令可以执行此操作?
我正在创建一个C-prog,它需要一个由17个整数组成的数组,所有整数都小于18并且是唯一的。这是我现在能做的: 我现在的算法是,每次rand()生成一个数字时,都会在数组中检查这个数字是否已经存在,如果已经存在,则rand()会继续生成一个数字,直到得到一个唯一的数字,然后将其存储在数组中,如果数组中不存在这样的数字,则直接输入到数组中。
问题内容: Oauth需要一个随机的64位无符号数字,以十进制格式编码为ASCII字符串。你们能帮我用php实现吗?谢谢 问题答案: 您可以使用两个32位数字,四个16位数字等。 PHP具有rand()和mt_rand(),但是标准没有指定它们提供多少随机位(尽管可以分别通过getrandmax()和mt_getrandmax()进行查询。) 因此, 最安全 最简单的选择就是生成64个随机位,并将
问题内容: 我不确定如何使用BigInteger类在Java中生成随机的n位整数。 问题答案: 然后您可以使用它:
本文向大家介绍C++生成不重复的随机整数,包括了C++生成不重复的随机整数的使用技巧和注意事项,需要的朋友参考一下 C++生成不重复的随机数,供大家参考,具体内容如下 给定正整数的范围[n,m],生成k个不重复的随机数字。 IDE是vs013。 运行结果: 这个程序可以用于班级内部按照学号进行随机抽签。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
我想使用c生成0-2^64范围内的非常大的随机数。我使用了rand()函数,但它没有生成非常大的数字。任何一个都可以帮助吗?