的文档Random.NextDouble():
返回大于或等于 0.0 且小于 1.0 的随机浮点数。
所以,它可以恰好为 0。但是这种情况的可能性有多大呢?
var random = new Random();
var x = random.NextDouble()
if(x == 0){
// probability for this?
}
Run Code Online (Sandbox Code Playgroud)
计算为 0 的概率很容易Random.Next(),但我不知道在这种情况下该怎么做......
正如评论中提到的,这取决于 的内部实现NextDouble。在“旧”.NET Framework 和现代 .NET 版本 5 之前,它看起来像这样:
protected virtual double Sample() {
return (InternalSample()*(1.0/MBIG));
}
Run Code Online (Sandbox Code Playgroud)
InternalSample返回 0 范围内的整数Int32.MaxValue,包括 0,int.MaxValue排除 0。我们可以假设 的分布InternalSample是均匀的(在只调用 的方法的文档中,有线索表明它是均匀的,并且似乎没有理由在整数的通用 RNG 中使用非均匀分布)。这意味着每个数字都有相同的可能性。那么,我们有 2,147,483,647 个数字在分布,抽到 0 的概率是 1 / 2,147,483,647。NextInternalSample
在现代 .NET 6+ 中有两种实现。当您向构造函数提供显式种子值时使用第一个Random。此实现与上面相同,用于兼容性原因 - 以便依赖种子值产生确定性结果的旧代码在迁移到新的 .NET 版本时不会中断。
第二个实现是一个新的实现,当您不将种子传递给Random构造函数时使用。源代码:
public override double NextDouble() =>
// As described in http://prng.di.unimi.it/:
// "A standard double (64-bit) floating-point number in IEEE floating point format has 52 bits of significand,
// plus an implicit bit at the left of the significand. Thus, the representation can actually store numbers with
// 53 significant binary digits. Because of this fact, in C99 a 64-bit unsigned integer x should be converted to
// a 64-bit double using the expression
// (x >> 11) * 0x1.0p-53"
(NextUInt64() >> 11) * (1.0 / (1ul << 53));
Run Code Online (Sandbox Code Playgroud)
我们首先获得随机的 64 位无符号整数。现在,我们可以将其乘以 1 / 2^64 以获得double0..1 范围内的值,但这会使结果分布产生偏差。double由 53 位尾数(52 位显式,1 位隐式)、指数和符号表示。对于所有整数值,指数都是相同的,因此我们有 53 位来表示整数值。但我们这里有 64 位整数。这意味着小于 2^53 的整数值可以精确表示,double但更大的整数则不能。例如:
ulong l1 = 1ul << 53;
ulong l2 = l1 + 1;
double d1 = l1;
double d2 = l2;
Console.WriteLine(d1 == d2);
Run Code Online (Sandbox Code Playgroud)
打印“true”,因此两个不同的整数映射到相同的double值。这意味着如果我们将 64 位整数乘以 1 / 2^64 - 我们将得到有偏差的非均匀分布,因为许多大于 2^53-1 的整数将映射到相同的值。
因此,我们扔掉 11 位,并将结果乘以 1 / 2^53,以获得 0..1 范围内的均匀分布。得到 0 的概率为 1 / 2^53 (1 / 9,007,199,254,740,992)。这种实现比旧的实现更好,因为它在 0 .. 1 范围内提供了更多不同的双精度数(旧实现中的 2^53 与 2^32 相比)。
您还在评论中询问:
如果知道 0 和 1 之间有多少个数字(根据 IEEE 754),就可以回答“概率”问题,因为 0 是其中之一
事实并非如此。在 IEEE 754 中,0..1 之间实际上有超过 2^53 个可表示的数字。我们有 52 位尾数,然后有 11 位指数,其中一半用于负指数。几乎所有负指数(大约是 11 位范围的一半)与尾数相结合,为我们提供了 0..1 范围内的不同值。
为什么我们不能使用 IEEE 允许我们生成随机数的完整 0..1 范围?因为这个范围不均匀(就像完整的双范围本身不均匀一样)。例如,0 .. 0.5 范围内的可表示数字比 0.5 .. 1 范围内的数字更多。
| 归档时间: |
|
| 查看次数: |
492 次 |
| 最近记录: |