如何在C++中生成非常大的随机数

8

我想使用c++生成0-2^64范围内的非常大的随机数。我已经尝试使用rand()函数,但它不能生成非常大的数字。请问有谁能够提供帮助吗?


2
非常大?一个简单的std::uint64_t可以容纳所有这些值。 - Kerrek SB
2
这是真的最佳复制目标吗?答案很糟糕,它们都使用了rand()在C++中不应该使用。 - Revolver_Ocelot
1
https://dev59.com/TZHea4cB1Zd3GeqPv-41#34209811 - Hatted Rooster
1
@πάνταῥεῖ 为什么?这不是重复吗?你找到更好的重复了吗? OP提问的数字并不比那边的数字小。 - Baum mit Augen
2
顺便说一下,如果范围实际上是[0,2^64),那么您可以跳过分配步骤,直接使用由std::mt19937_64返回的值。 - Baum mit Augen
显示剩余12条评论
6个回答

22

使用C++11标准的随机库,你可以这样做:

#include <iostream>
#include <random>

int main()
{
  /* Seed */
  std::random_device rd;

  /* Random number generator */
  std::default_random_engine generator(rd());

  /* Distribution on which to apply the generator */
  std::uniform_int_distribution<long long unsigned> distribution(0,0xFFFFFFFFFFFFFFFF);

  for (int i = 0; i < 10; i++) {
      std::cout << distribution(generator) << std::endl;
  }

  return 0;
}

演示


1
从来没有见过将“API”这个词用于此。 - Hatted Rooster
这个解决方案只能生成大型数字。如果我想生成范围在0-2^64之间的数字怎么办? - Nabeel_Afzal
4
@Nabeel_Afzal 这个解决方案确实能够生成在区间 [0, 2^64-1] 内的数字。但由于这些数字是完全随机并且在该区间内等概率选择的,因此生成的数字中有99%会超过2^56,因为区间 [2^56, 2^64] 的范围比区间 [0, 2^56] 大100倍以上。 - coyotte508
你可以将数字进行模运算,使其变小,例如 myrnd %= 10000000000LL; - Déjà vu
Déjàvu更希望在事后更改分布参数而不是对生成的数字进行MOD操作。 - Mathieu Pagé

6
作为范围在[0,2^64)内的均匀随机数只需使用64个随机位,您可以直接使用std::mt19937_64的返回值:
#include <random>

int main () {
    std::mt19937_64 gen (std::random_device{}());

    std::uint64_t randomNumber = gen();
}

请注意,用单个32位种子初始化Mersenne Twister引擎不是最佳方式。有更好的方法,请参考此链接
此外请注意,如今通常不建议使用rand函数。Stephan T. Lavavej在这个视频中讨论了这个话题。

2

1

我编写了一个生成随机19位数字的函数,它与标准的rand()函数完全相同。它从19位数字中抽取每个数字并将其存储在数组中,然后将它们组合在一起生成非常大的随机数。

unsigned long long Randomize()
{
    unsigned long long randnumber = 0;
    int digits[20];

    for (int i = 19; i >= 1; i--)
    {
      digits[i]=rand()%10:
    }
    for(int i=19; i>=1; i--)
    {
       unsigned long long power = pow(10, i-1);

        if (power%2 != 0 && power != 1)     //eliminates "bug" (which comes from long long power is not a float))
            power++;

        randnumber += power * digits[i];
    }
return randnumber;
}

要使用此功能,您需要实现几个库。

#include <stdlib.h>
#include <time.h>
#include <math.h>

例子:
srand(time(NULL));
randomnumber = Randomize()%10000000+10000000;

在这种情况下,随机数是从10000000到20000000之间的数字。

0

虽然回答有点晚,但这里提供一个简单的方法

我们知道在c++中rand()函数可以生成接近32767的随机数(来源:https://www.geeksforgeeks.org/rand-and-srand-in-ccpp/) 但是如果我们像这样做:

long long random_num = (rand() * rand()) % 1000000000

那么它保证生成的随机数比32767大得多。模数将确定随机数中的数字数量。


两个数相乘的计算成本较高,因此我认为这不是最优解。 - Avelanche

-2
如果您的rand()函数只返回[0, 2^15)范围内的数字,则可以将rand()返回的5个数字连接起来,以获得[0, 2^64)范围内的数字。
当然,还有其他可能的解决方案(可能更好)。C++库中的rand()函数通常是一个线性同余生成器。您可以使用相同的数学原理简单地实现自己的生成器。
例如,以下代码生成64位随机数:
unsigned long long rand64()
{
    static unsigned long long seed;
    seed = seed * 6364136223846793005 + 1442695040888963407;
    return seed;
}

参数63641362238467930051442695040888963407是Donald Knuth使用的参数。

该方法的优缺点在上述维基页面中进行了讨论。如果不需要高质量的随机性,则这可能是一个不错的选择。


3
为什么要使用异或(XOR)运算符?为什么要选择20位的数据段?您能否详细解释一下这些神奇的数字吗? - πάντα ῥεῖ
2
请问您能否解释一下return语句背后的逻辑? - Nidhin David
32768 只是2的15次方,因此将这些移位操作 20 次不会填满所有位。 - interjay
1
不要使用 rand() 函数,它生成的随机数非常差。相反,请使用 <random> 中提供的工具。对于非常大的数字(大于 2^64),可以考虑使用 GMP 库中的函数。 - Jesper Juhl
这么多转换(甚至是C风格的)。毫无意义的异或操作(至少我看不出来有什么意义)。呃。 - Jesper Juhl
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接