RAND_MAX和UINT_MAX之间的差异会有所不同吗?

Will the difference between RAND_MAX and UINT_MAX vary?

本文关键字:MAX 有所不同 UINT 之间 RAND      更新时间:2023-10-16

我的作业是在02^30之间随机取整数。现在,在过去,我们已经知道rand()只返回到RAND_MAX的整数,这小于UINT_MAX,我们可以使用位移位来填充UINT_MAX的容量。从我所做的一些阅读(这里,在SO上),我意识到如果这些数字的分布对我很重要,这可能不是一个很好的主意。话虽如此,我的教授已经指定了这个方法。

我的问题是,位移位多少?RAND_MAXUINT_MAX之间的差异是否总是存在一个安全常数来进行位移?或者需要进行一些初始探测来确定要进行位移的数字?我应该保持位移一点并检查UINT_MAX吗?

我问的原因是,UINT_MAX被定义为至少是一个特定的数字(65535),但在我的机器上UINT_MAX要大得多(4294967295)。这让我担心我可能会在周末完成作业,到达学校,发现一切都不够好,不能提交。

谢谢!

引用:

我读过几个类似的问题,但没有得到答案。

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

生成0 ~ n范围内的随机数,其中n可以为> RAND_MAX

实际上,上面的第二个问题让我质疑这样做的价值。

您的问题集中在RAND_MAXUINT_MAX之间是否有一点变化。这就归结为UINT_MAXRAND_MAX是否为2^k - 1形式的问题。UINT_MAX几乎肯定会出现在任何基于二进制数系统的计算机上。如果sizeof(int)=32位,则k=32位,如果sizeof(int)=64 bit位,则k=64位,依此类推。现在我们可以考虑RAND_MAX。在大多数实现中,答案是RAND_MAX几乎总是形式为2^k - 1。为什么?我们需要考虑rand()的大多数实现实际上是如何工作的。

  1. rand()通常使用线性同余生成器(参见http://en.wikipedia.org/wiki/Linear_congruential_generator或Knuth"计算机程序员的艺术第2部分:半数值算法")。基本上,随机数是一个带有seed

    的序列

    x(k+1) = (a x(k) + c) % m

(即。C库存储最后一次迭代的x(k),当你调用rand()时,它返回x(k+1))

  1. 为了保证良好的质量,必须仔细选择发生器的参数(acm)。质量通常涉及在序列重复之前的次数,等等。选择这些参数时的一个矛盾是使m尽可能接近UINT_MAX,以避免浪费潜在的随机位。如果您研究了生成器,通常正确的选择是使mUINT_MAX小一些。您还需要使m为素数

  2. 通常您希望rand()尽可能快,因此您希望这些操作便宜。计算mod最便宜的形式是foo % (2^k - 1),因为它可以被实现为foo & (1<<k-1)。对于k的特殊选择,您将获得梅森prime。

例如,一个常见的选择是k=31,它产生质数2^31-1 = 2147483647。这是32位整数的典型选择,其中UINT_MAX=2^32-1 = 4294967295。对于64位数字,我们有UINT_MAX=2^64-1=18446744073709551615,而RAND_MAX的选择将是2^61-1 = 2305843009213693951

所以总的来说,回答你的问题:在大多数实现中,你可以假设有一个简单的位移位,但是,没有真正的保证。至少应该在程序初始化时进行运行时测试。如果您正在使用c++,一个更好的做法是使用static_assert在编译时检测您的假设是否为真,如果不为真则编译失败。Boost有这样一个静态断言,就像最近批准的标准c++ 11一样……也就是说,可以这样做(虽然可能需要一些工作来编写is_power_of_two_minus_one的静态版本):

unsigned int myrand()
{
        static_assert(sizeof(int)==4,"sizeof(unsigned int) != 4");
        static_assert(is_power_of_two_minus_one(RAND_MAX),"RAND_MAX not a power of two minus one");
        static_assert(is_power_of_two_minus_one(UINT_MAX),"UINT_MAX not power of two minus one");
        unsigned int raw_rand=rand();
        // do your bit shift to adjust raw_rand
        return raw_rand;
}

实际上,上面的第二个问题让我质疑这样做的价值。

如果你的教授告诉你这样做,你应该这样做。这当然不是加密强度,但对于家庭作业的目的,它将是好的。

对于RAND_MAX2^n - 1,我通常会这样假设。计算机每次生成随机数的方式是一组位数,所以如果最大值不是2^n - 1,要么不是返回范围内的所有数字,要么会浪费熵。

至于在所有系统上的差异是相同的,我强烈建议不要这样假设。在你的代码中,找出每个字符中有多少位,并动态地找出如何移位。

你不能ssh到你将(最终)运行这个的学校服务器吗?