C++ RAND_MAX 的值总是 (2^n)-1 吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4945698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:58:50  来源:igfitidea点击:

Is the value of RAND_MAX always (2^n)-1?

c++random

提问by Steve314

I'm interested for C++, though I suspect that simply imports the C standard definition. I believe the answer is no for what the standard says, but I'm most interested in the in-practice answer.

我对 C++ 感兴趣,尽管我怀疑它只是导入了 C 标准定义。我相信标准所说的答案是否定的,但我对实践中的答案最感兴趣。

If RAND_MAX is always (2^n)-1 (where n is some natural number - in effect the number of random binary digits in a random number), that simplifies dealing with an issue that turned up recently moving code from MinGW GCC to Linux GCC. RAND_MAX seems to be bigger (I didn't check, but possibly equal to INT_MAX or whatever the symbol is), so some old naively written RAND_MAX-isn't-big-enough-so-work-around-it code backfired. Now I need to decide just how general I need this library to be, considering the fiddliness of writing code that copes correctly with the possibility of overflow without making assumptions about e.g. the width of an int.

如果 RAND_MAX 始终为 (2^n)-1(其中 n 是某个自然数 - 实际上是随机数中随机二进制数字的数量),则可以简化处理最近将代码从 MinGW GCC 移动到 Linux 的问题海湾合作委员会。RAND_MAX 似乎更大(我没有检查,但可能等于 INT_MAX 或任何符号),所以一些旧的天真写的 RAND_MAX-不够大所以解决它的代码适得其反。现在我需要决定我需要这个库有多通用,考虑到编写正确处理溢出可能性的代码的繁琐,而不对例如 int 的宽度做出假设。

Anyway, are there any reasonably widely used C++ compilers that use something other than (2^n)-1 for RAND_MAX?

无论如何,是否有任何合理广泛使用的 C++ 编译器对 RAND_MAX 使用除 (2^n)-1 以外的其他内容?

Also, am I correct that ((RAND_MAX | (RAND_MAX >> 1)) == RAND_MAX) is always and only true if RAND_MAX is equal to ((2^n)-1) for some unsigned integer n. I believe RAND_MAX is technically an int, but it makes no sense to have a negative or fractional value, so I think I can safely discount those. Bit-fiddling doesn't normally bother me, but I keep thinking the expression looks wrong, and I can't figure out why.

另外,对于某些无符号整数 n,((RAND_MAX | (RAND_MAX >> 1)) == RAND_MAX) 始终且仅当 RAND_MAX 等于 ((2^n)-1) 时,我是否正确。我相信 RAND_MAX 从技术上讲是一个整数,但有一个负值或小数值是没有意义的,所以我想我可以安全地对它们进行折扣。摆弄位通常不会打扰我,但我一直认为表情看起来不对劲,我不知道为什么。

Finally, although I'm not going to be happy until I've got a working solution of my own, what shouldI be using for random numbers rather than write it myself? I need random numbers in the range 0 <= x < parameter, and I especially want as-equal-as-sanely-possible probabilities for all numbers. For example, taking (rand() % upperbound) gives a bias towards smaller values, especially when the upperbound is large - I want to avoid that.

最后,虽然在我有自己的工作解决方案之前我不会高兴,但我应该为随机数使用什么而不是自己编写它?我需要 0 <= x < 参数范围内的随机数,我特别希望所有数字的概率都相等。例如,取 (rand() % upperbound) 会偏向于较小的值,尤其是当上限很大时 - 我想避免这种情况。

Is there a Boost or C++0x thing for that?

有 Boost 或 C++0x 的东西吗?

EDIT

编辑

Following something in the "Related" bit on the side of the page shows there is indeed a way to get random numbers with given lower and upper bounds in boost.

按照页面一侧“相关”位中的内容显示,确实有一种方法可以获取具有给定下限和上限的随机数。

采纳答案by Fred Foo

I don't know what the guarantees on RAND_MAXare, but you'd better avoid it if possible because of the number of broken implementations around and because it starts cycling quite quickly in today's applications. Getting a uniform distribution is described here.

我不知道有什么保证RAND_MAX,但是如果可能的话,你最好避免它,因为周围有很多损坏的实现,并且因为它在今天的应用程序中开始循环非常快。此处描述如何获得均匀分布。

I recommend Boost.Randominstead. The Mersenne twistergenerator represents a good tradeoff between speed, memory use and quality.

我推荐Boost.Random代替。在梅森捻线机发电机代表了速度,内存使用和质量之间的良好平衡。

回答by AProgrammer

  • I don't know any implementation for which RAND_MAX is not one less than a power of two, but that isn't mandated by the standard;

  • ((RAND_MAX | (RAND_MAX >> 1)) == RAND_MAX) is indeed a way to test if RAND_MAX is one less than a power of two.

  • I'm using

    int alea(int n){ 
      assert (0 < n && n <= RAND_MAX); 
      int partSize = 
        n == RAND_MAX ? 1 : 1 + (RAND_MAX-n)/(n+1); 
      int maxUsefull = partSize * n + (partSize-1); 
      int draw; 
      do { 
        draw = rand(); 
      } while (draw > maxUsefull); 
      return draw/partSize; 
    }
    
  • 我不知道 RAND_MAX 不小于 2 的幂的任何实现,但这不是标准规定的;

  • ((RAND_MAX | (RAND_MAX >> 1)) == RAND_MAX) 确实是一种测试 RAND_MAX 是否小于二的幂的方法。

  • 我正在使用

    int alea(int n){ 
      assert (0 < n && n <= RAND_MAX); 
      int partSize = 
        n == RAND_MAX ? 1 : 1 + (RAND_MAX-n)/(n+1); 
      int maxUsefull = partSize * n + (partSize-1); 
      int draw; 
      do { 
        draw = rand(); 
      } while (draw > maxUsefull); 
      return draw/partSize; 
    }
    

to make as evenly distributed as possible random numbers from rand().

从 rand() 生成尽可能均匀分布的随机数。

回答by Alexandre C.

For implementations of randwhich use a (variant of a) Linear Congruential Generator (most of them), then RAND_MAX will be a prime number, not necessarily of the form 2n- 1 (a "Mersenne prime").

对于rand使用(a)线性同余生成器(大多数)的实现,那么 RAND_MAX 将是一个素数,不一定是 2 n- 1(“梅森素数”)的形式。

Also, 231-1 is a prime number, but if n is not prime, 2n- 1 is not prime.

此外,2 31-1 是素数,但如果n 不是素数,则2 n- 1 也不是素数。

(Indeed, if n = ab, then 2n- 1 = (2a- 1)(1 + 2b+ 22b+ ...) )

(确实,如果 n = ab,则 2 n- 1 = (2 a- 1)(1 + 2 b+ 2 2b+ ...) )

Around 264, the only Mersenne prime is 261- 1.

在 2 64附近,唯一的梅森素数是 2 61- 1。

And you should really avoid linear congruential generators if you have any half serious requirement about random number generation. Actually, I'd say that except for a tetris game, you should avoid rand()from the C library.

如果您对随机数生成有任何半认真的要求,那么您真的应该避免使用线性同余生成器。实际上,我想说除了俄罗斯方块游戏之外,您应该避免rand()使用 C 库。

回答by Tomas Kubes

In GCC (4.6) RAND_MAX = 0x7FFFFFFF (31bit) In MS Visual Studio (2012) RAND_MAX = 0x7FFF (15bit)

在 GCC (4.6) RAND_MAX = 0x7FFFFFFF (31bit) 在 MS Visual Studio (2012) RAND_MAX = 0x7FFF (15bit)

回答by Bhaskar

In Embacadero C++ Builder, there are two variables defined in stdlib.h:

在 Embacadero C++ Builder 中,stdlib.h 中定义了两个变量:

/* Maximum value returned by "rand" function*/
#define RAND_MAX  0x7FFFU

/* Maximum value returned by "_lrand" function (also used by random() macro)*/
#define LRAND_MAX 0x7FFFFFFFU

回答by texadactyl

In the standard GNU header file, stdlib.h, there is a definition of RAND_MAX which should be the sole definition in your system:

在标准 GNU 头文件 stdlib.h 中,有一个 RAND_MAX 定义,它应该是您系统中的唯一定义:

#define RAND_MAX    2147483647

The value 2147483647 = 0x7fffffff is the largest unsigned 32-bit integer.

值 2147483647 = 0x7fffffff 是最大的无符号 32 位整数。

The rand functions, defined in stdlib.h, are reliable in standard GNU environments with one caveat: multi-threading (pthread) environments will need pthread code to synchronize in order to protect the rand(), srand(), and rand_r() calls since they are not reentrant. See the man page for srandfor an explanation.

stdlib.h 中定义的 rand 函数在标准 GNU 环境中是可靠的,但有一个警告:多线程 (pthread) 环境将需要 pthread 代码进行同步以保护 rand()、srand() 和 rand_r()调用,因为它们不可重入。有关解释,请参阅srand手册页

RAND_MAX should not be defined anywhere else in your system. If you are seeing a different value for RAND_MAX or seeing a definition of RAND_MAX somewhere besides stdlib.h, then this must be a non-standard, non-portable environment. Windows is notorious for making standardization and portability difficult (E.g. sockets implementation and APIs).

RAND_MAX 不应在系统中的任何其他地方定义。如果您看到 RAND_MAX 的不同值或在 stdlib.h 之外的某处看到 RAND_MAX 的定义,那么这一定是一个非标准、不可移植的环境。Windows 因使标准化和可移植性变得困难(例如套接字实现和 API)而臭名昭著。

回答by vinc17

According to both ISO C (C99 to C17 at least) and POSIX (Issue 7, 2016 Edition), RAND_MAXshall be at least 32767, i.e. 215?1, and there are no other restrictions.

根据 ISO C(至少 C99 到 C17)和 POSIX(第 7 期,2016 版),RAND_MAX至少应为 32767,即 2 15?1,没有其他限制。

Under GNU/Linux, RAND_MAXis guaranteed to be exactly 2147483647 = 231?1 on all architectures for consistency with POSIX concerning the random()function: POSIXspecifies that the return value is in the range from 0 to 231?1, and the Linux random(3)man page documents the range as being from 0 to RAND_MAX.

在 GNU/Linux 下,为了与 POSIX 关于函数的一致性,在所有体系结构上RAND_MAX保证恰好是 2147483647 = 2 31?1 random()POSIX指定返回值在 0 到 2 31?1的范围内,并且 Linux随机( 3)手册页将范围记录为从 0 到RAND_MAX.