当前位置: 首页 > 知识库问答 >
问题:

如何在C中生成随机的64位无符号整数

邓崇凛
2023-03-14

我需要使用C生成随机64位无符号整数。我的意思是,范围应该是018446744073709551615RAND_MAX1073741823

我在链接中发现了一些解决方案,这些解决方案可能是重复的,但答案大多连接了一些rand()结果或进行一些增量算术运算。因此,结果始终是 18 位或 20 位数字。我还想要像51133387这样的结果,而不仅仅是3771778641802345472

顺便说一句,我真的没有太多的C经验,但任何方法,代码示例和想法都是有益的。

共有3个答案

耿学义
2023-03-14

如果您有足够好的随机字节源(例如,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位或更多的十进制数字,所以这实际上是你最可能得到的。

欧阳绪
2023-03-14

如果您不需要加密安全的伪随机数,我建议您使用MT19937-64。它是梅森·费尔托斯特PRNG的64位版本。

请不要组合rand()输出,也不要使用其他技巧。使用现有实现:

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html

东门修文
2023-03-14

关于“结果总是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()函数,但它没有生成非常大的数字。任何一个都可以帮助吗?