我的猜测是,这只是从区间 [0,1] 上的均匀分布产生一个随机数;这是正确的吗?
没有。代码可能永远不会返回 1.0f 或统一的结果。
#define random ((float) rand() / (float)((1 << 31) - 1)) 有很多问题。这是弱代码。
精度损失:典型的float 具有大约 24 位精度。将rand() 的结果转换为超过24 位的结果为float,由于四舍五入,其值可能与原始值不同。这会削弱/破坏随机数生成的一致性。不同的rand() 结果会得出相同的答案。另见@Olaf
对此的修复是有问题的,因为 OP 显然希望从集合 [0, 1/2,147,483,648, 2/2,147,483,648, ... 2,147,483,647/2,147,483,648] 中获得一个统一的随机数,鉴于@987654329 的可能精度限制,这是不可能的@。
最糟糕的是,(1 << 31) 是 未定义的行为 UB,除非 int 至少有 33 位长。将 1 移到符号位置是 UB。 C11dr §6.5.7 4.
要避免 UB,请使用 ((1ul << 31) - 1)。
然而,使用幻数 ((1ul << 31) - 1) 不如基于 RAND_MAX 的分数那么可靠。
进一步(float) ((1ul << 31) - 1) 可能会遭受如上所述的精度损失,因为它形成了值2147483648.0f,而不是无法获得的2147483647.0f。 OP 的代码可能永远生成1.0f。
我怀疑 OP 确实需要 [0..1) 结果而不是 [0..1]。两者都在下面。
// generate a `double` in the range [0 ... 1)
#define random0to_almost1 (rand() / (RAND_MAX + 1.0))
// or
// generate a `double` in the range [0 ... 1]
#define random0to1 (rand() / (RAND_MAX + 0.0))
请注意,如果double 的精度(通常为 53 位)超过了RAND_MAX 的需要,这将像 OP 的原始代码一样受到影响。
为了应对,一个缓解步骤是确保RAND_MAX + 1.0 准确完成。在非常常见中,但未指定 C,RAND_MAX 是 2_minus_1 的幂。所以RAND_MAX/2 + 1 是int 和精确 2 的幂。将int 转换为double 肯定是精确。
#define random0to_almost1 (rand() / (2.0*(RAND_MAX/2 + 1)))
float 解决方案是
// This value is platform dependent, but very common
// Do not a a highly portable generation method yet.
#define FLT_POWER2_INTEGER_LIMIT (1ul << 24)
#define random0to_almost1 ( \
(rand() % FLT_POWER2_INTEGER_LIMIT) / \
(RAND_MAX % FLT_POWER2_INTEGER_LIMIT + 1.0f) \
)