[a, b) 上的均匀真实分布几乎与分布[a, b] 在统计上无法区分。
这两个分布之间的statistical distance 几乎等于一除以a 和b 之间的浮点数。
也就是说,对于任何给定样本,没有返回0 或1 的统计检验,因此观察到具有第一个分布的1 的概率与观察到@ 的概率不同987654329@ 与第二次分发相比,超过2^{-32}。 (假设您正在开车,例如 std::uniform_real_distribution<float> 使用来自 std::random_device 的纯熵。)
因此在大多数实际应用程序中没有有意义的区别。
如果您想做类似的事情,请使用(a, b] 范围,以防止(极不可能)除以零错误或其他东西,您可以测试您是否完全得到a 并将其替换为@987654335 @如果它是某种关键系统。
FWIW 我也怀疑你的“b 之后的下一个”的解决方案并不总是像你想的那样——在大多数情况下,将会发生的事情是,适配器会将 b - a 计算为浮点数数字,然后从熵源中取一个样本,使用静态转换将其转换为0-1 范围内的浮点数,然后乘以因子b-a,加上a 并返回结果。
如果a 和b 的比例不完全相同,那么b 中的ε 变化很可能会在浮点减法中丢失,那么这种变化就没有效果。
这不是错误的原因是该标准不要求分发适配器精确生成指定的分发,只要求它在近似意义上收敛到目标。
该标准严格保证分发不会产生超出其规定范围的内容:
26.5.8.1 一般 [rand.dist.general]
1. 从本节 26.5.8 中指定的类模板实例化的每种类型都满足
随机数分布 (26.5.1.6) 类型。
...
3. 生成每个指定分布的算法是实现定义的。
4.指定每个概率密度函数p(z)和每个离散概率函数P (z i )的值
在此部分中是0 在其指定域之外的任何地方。
但是,该标准也提到了统一随机数生成器:
26.5.3.1 [rand.req.urng]
1. 统一随机数生成器 g 类型为 G 是一个返回无符号整数值的函数对象,例如
可能结果范围内的每个值(理想情况下)返回的概率相等。 [注:
g 的结果接近理想的程度通常由统计确定。 ——尾注]
由于[a, b) 和[a, b + epsilon) 在统计上基本上无法区分,因此即使使用b + epsilon 技巧,您仍然不会在输出中看到b,即使您彻底尝试所有可能的种子。
如果这不是标准的观点,那么所有这些适配器都必须精心编写,以便它们始终能够在每个架构上获得完全正确的分布,而且它们的运行速度会慢得多。在大多数应用中,像这样的微小采样不准确是可以容忍的,更重要的是要高效。