【发布时间】:2021-07-20 08:29:29
【问题描述】:
我正在审查一个为基数映射生成键的函数,发现 rand() 的实现对我来说很新颖。
函数如下:
static int make_random(RadixMap *map)
{
size_t i = 0;
for (i = 0; i < map->max - 1; i++){
uint32_t key = (uint32_t) (rand() | (rand() << 16));<--This was interesting
check(RadixMap_add(map, key, i) == 0, "Failed to add key %u", key);
}
return i;
error:
return 0;
}
----- Type definitions --------
typedef union RMElement {
uint64_t raw;
struct {
uint32_t key;
uint32_t value;
} data;
} RMElement;
typedef struct RadixMap {
size_t max;
size_t end;
uint32_t counter;
RMElement *contents;
RMElement *temp;
} RadixMap;
来自 Zed Shaw 的 ex35 Learn C the Hard Way
我发现有趣的具体部分是
uint32_t key = (uint32_t) (rand() | (rand() << 16)); <-- This was interesting
这对我来说很有趣,因为它本来可以简单地做 ..
uint32_t key = rand();
由于 RAND_MAX (0x7FFFFFFF) 小于 uint32_t MAX (0xFFFFFFFF)
移位实现看起来具有以下优点。
- 允许更大的随机值范围,0xFFFFFFFF 与 0x7FFFFFFF
- 值(初始 0 除外)至少为 5 位十进制 (65537) (0x10001)
- 看到“0”的概率降低。
还有以下缺点
- 增加代码复杂度?
还有其他原因使用 rand() 的移位实现吗?
我一直试图在我的代码审查中找出使用此实现的原因,并希望确保我的想法是正确的。
【问题讨论】:
-
在实际生产代码中,如果你想要真正的随机性和安全性,你不应该一开始就使用 rand/srand。我想测试没问题,但看看 /dev/random 和 rdrand
-
除了减少数字的随机性之外?通过使用
|- 你失去了很多你的范围。我希望至少有一个^。基本上,只要您多次调用 random 以形成一个值,您“可能”就会失去分布。我想您可以关闭高 16 位,然后将这些值放在一起以获得您描述的分布,但我宁愿使用更现代的 rand() 函数。 -
该代码在
RAND_MAX = 0x7FFF(windows)(使第 16 位卡在零)和RAND_MAX = 0x7FFFFFFF(linux)(中间位有 75% 的机会被设置)都不正确。所以基本上,这是书中的一个错误。
标签: c