【问题标题】:getting random numbers larger than RAND_MAX获取大于 RAND_MAX 的随机数
【发布时间】:2014-01-28 22:41:59
【问题描述】:

Accelerated C++ by Andrew Koenig 的问题 7-9 提问:

7-9。 (困难)第 7.4.4/135 节中 nrand 的实现不会 适用于大于 RAND_MAX 的参数。通常,这个限制是 没问题,因为 RAND_MAX 通常是可能的最大整数 反正。尽管如此,还是有 RAND_MAX 的实现 远小于可能的最大整数。例如,它是 RAND_MAX 为 32767 (2^15 -1) 和最大的并不少见 可能的整数为 2147483647 (2^31 -1)。重新实现 nrand 以便 它适用于所有 n 值。

如果n > RAN_MAX我的想法是采取

double temp = n/RAN_MAX + .5;
int mult = temp;
int randomNum = 0;

for (int i = 0; i != mult; mult++)
    randomNum += rand();

然后测试看看randomNum > RAND_MAX吗?我不知道如何使用比我的计算机可以处理的更大的整数,所以我认为没有任何真正的方法可以告诉。

【问题讨论】:

  • 假设你掷了两个骰子并把结果相加。 12 和 7 一样吗?
  • 正确。谢谢你
  • 对解决这个问题有什么想法吗?
  • 假设我掷出一个骰子,将结果乘以 6,然后加上掷出第二个骰子的结果。这样会更好吗?
  • 哦,我明白了:)。现在我将尝试将其扩展到我的问题。感谢您的帮助。

标签: c++


【解决方案1】:

如果您真的在处理大于计算机处理能力的整数,那就太复杂了。

但是对于大于int 的整数,您确实有几个选项,其中包括:unsigned intlongunsigned longlong longunsigned long long,按大小递增的顺序排列。数字的大小取决于您的架构。

例如,在我的机器上,我有以下内容:

Data Type:   Bytes  Minimum               Maximum
Short SInt:  2      -32768                32767
Short UInt:  2      0                     65535
UInt:        4      0                     4294967295
SInt:        4      -2147483648           2147483647
ULong:       8      0                     18446744073709551615
SLong:       8      -9223372036854775808  9223372036854775807
ULong Long:  8      0                     18446744073709551615
SLong Long:  8      -9223372036854775808  9223372036854775807

因此,如您所见,您可以使数字远大于 int 和 32767。

一种方法如下:

double a=rand()/(double)RAND_MAX;
unsigned long long random_n=(unsigned long long)(BIG_MAXIMUM_NUMBER*a);

但是,由于浮点数的离散性,这可能意味着某些值永远不会出现在您的输出流中。

C++11 有一个 库,它解决了这个问题和你提到的问题。其用法示例如下:

const int min = 100000;
const int max = 1000000;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(min,max);
int random_int = distribution(generator);

只需更改数据类型以满足您的大需求。

另一种看待这个问题的方式是,我们可以将rand() 解释为返回一个位域,并且由于它是一个统一的 PRNG,所有位域的可能性相同。然后我们可以多次调用rand() 来获得多个同样可能的位字段并将它们合并以产生大数字。下面是我们如何从两个 8 位随机数中生成一个 16 位随机数:

uint16 a=(uint16)(rand()&255);
uint16 b=(uint16)(rand()&255);
uint16 random_int=b<<8 | a;

rand()&amp;255 只保留rand() 返回的任何数字的 8 个最低有效位;也就是说,它只保留rand()的最后一个字节。

(uint16) 将此字节转换为无符号的 16 位数字。

a&lt;&lt;8a 的位向左移动 8 位,这为安全添加 b 腾出了空间。

但是如果rand() 返回一个有符号值,使得最高有效位始终为 0 或 1,该怎么办?然后我们可以执行以下操作:

uint16 a=(uint16)(rand()&255);
uint16 b=(uint16)(rand()&255);
uint16 c=(uint16)(rand()&1);
uint16 random_int=c<<14 | b<<7 | a;

我们仅将b 左移 7 位,因此第 8 个最低有效位是随机的。这意味着第 14 位和第 15 位最低有效位将是非随机的。由于我们想模仿rand() 的行为,我们将第 15 个最低有效位保留为非随机位,并抓取一个随机位左移到第 14 个 LSB 的位置。

【讨论】:

  • 当您从stackoverflow.com/questions/13503671/… 中复制上面使用uniform_int_distribution 时,您删除了有关播种生成器的注释。这可能很重要。
  • @BenjaminBannier,注意只是应该正确地为生成器播种。 cstdlib 的rand() 也应该如此。讨论这可能与这里的兴趣点不同。
猜你喜欢
  • 1970-01-01
  • 2012-11-10
  • 2022-06-16
  • 2015-03-22
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 2014-12-27
  • 1970-01-01
相关资源
最近更新 更多