RAND_MAX和UINT_MAX之间的差异会有所不同吗?
Will the difference between RAND_MAX and UINT_MAX vary?
我的作业是在0
和2^30
之间随机取整数。现在,在过去,我们已经知道rand()
只返回到RAND_MAX
的整数,这小于UINT_MAX
,我们可以使用位移位来填充UINT_MAX
的容量。从我所做的一些阅读(这里,在SO上),我意识到如果这些数字的分布对我很重要,这可能不是一个很好的主意。话虽如此,我的教授已经指定了这个方法。
我的问题是,位移位多少?RAND_MAX
和UINT_MAX
之间的差异是否总是存在一个安全常数来进行位移?或者需要进行一些初始探测来确定要进行位移的数字?我应该保持位移一点并检查UINT_MAX
吗?
我问的原因是,UINT_MAX
被定义为至少是一个特定的数字(65535
),但在我的机器上UINT_MAX
要大得多(4294967295
)。这让我担心我可能会在周末完成作业,到达学校,发现一切都不够好,不能提交。
谢谢!
引用:
我读过几个类似的问题,但没有得到答案。
RAND_MAX
的值总是(2^n)-1
吗?
生成0
~ n
范围内的随机数,其中n
可以为> RAND_MAX
实际上,上面的第二个问题让我质疑这样做的价值。
您的问题集中在RAND_MAX
和UINT_MAX
之间是否有一点变化。这就归结为UINT_MAX
和RAND_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()
的大多数实现实际上是如何工作的。
-
的序列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)
)
-
为了保证良好的质量,必须仔细选择发生器的参数(
a
、c
和m
)。质量通常涉及在序列重复之前的次数,等等。选择这些参数时的一个矛盾是使m
尽可能接近UINT_MAX
,以避免浪费潜在的随机位。如果您研究了生成器,通常正确的选择是使m
比UINT_MAX
小一些。您还需要使m
为素数 -
通常您希望
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_MAX
是2^n - 1
,我通常会这样假设。计算机每次生成随机数的方式是一组位数,所以如果最大值不是2^n - 1
,要么不是返回范围内的所有数字,要么会浪费熵。
至于在所有系统上的差异是相同的,我强烈建议不要这样假设。在你的代码中,找出每个字符中有多少位,并动态地找出如何移位。
你不能ssh到你将(最终)运行这个的学校服务器吗?
- <streamsize>C++ 中 numeric_limits::max() 的值
- 黑客级别的Mini-Max Sum
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- GCC和Clang在与__builtin_constant_p相关的static_assert方面有所不同
- 关于 std::min, std::max 中的比较运算符的混淆
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- std::max() 函数与定点实现的比较中的问题
- 使用 CImg 库的 std::min 和 std::max 的编译问题
- 在 3ds Max 中更新进度条后,环境和效果 UI 不刷新
- 从自定义类获取对象向量中的 max 元素
- 如何在C++中递归地找到max元素的索引?
- SFINAE 与 numeric_limits<T>::max() 在 MSVC2017 上
- 这句话是什么意思 - " vector<long long> distance(n, std::numeric_limits<long long>::max()); "?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 在f2c.h文件中定义min()max()宏时出错
- c++curl返回413请求实体过大,但是post大小远小于max大小
- 在枚举类型上使用std::max是不是一种糟糕的做法
- 为什么Visual Studio 2019不支持用于减少Openmp的关键字"max"?
- 重载函数仅在返回类型上有所不同
- 没有函数模板的实例"max"与参数列表参数类型匹配(int、int)