bounty将在5天后过期。回答此问题可获得+50的声誉奖励。ndsvw正在寻找此问题的更详细的答案。
Random.NextDouble()
的文档:
返回大于或等于0.0且小于1.0的随机浮点数。
所以,它可以正好是0,但这个概率有多大呢?
var random = new Random();
var x = random.NextDouble()
if(x == 0){
// probability for this?
}
计算Random.Next()
为0的概率很容易,但我不知道在这种情况下如何计算......
3条答案
按热度按时间rhfm7lfc1#
正如在注解中提到的,它依赖于
NextDouble
的内部实现。在“旧的”.NET框架中,以及在最高版本5的现代.NET中,它看起来像这样:InternalSample
返回0到Int32.MaxValue
范围内的整数,包括0,不包括int.MaxValue
。我们可以假设InternalSample
的分布是均匀的(在用于Next
的docs方法中,该方法只调用InternalSample
,有线索表明它是,似乎没有理由在通用的整数RNG中使用非均匀分布)。这意味着每个数字的概率都相等。那么,我们有2,147,483,647个数字处于分布中,抽到0的概率是1 /2,147,483,647。在现代的.NET 6+中有两种实现。第一种是在您向
Random
构造函数提供显式种子值时使用的。这种实现与上面的相同,并且是出于兼容性原因而使用的-以便依赖种子值来产生确定性结果的旧代码在移动到新的.NET版本时不会中断。第二个实现是一个新的实现,当您不将seed传递到
Random
构造函数时使用。源代码:我们首先获得随机的64位无符号整数,现在,我们可以将其乘以1 / 2^64以获得0..1范围内的
double
,但这会使结果分布有偏差。double
由53位尾数表示(52位是显式的,1位是隐式的)、指数和符号。对于所有整数值,指数是相同的,所以我们只剩下53位来表示整数值,但这里有64位整数,这意味着小于2^53的整数值可以用double
来表示,但更大的整数不能,例如:打印“true”,两个不同的整数Map到相同的
double
值,这意味着如果我们将64位整数乘以12^64,我们将得到一个有偏的非均匀分布,因为许多大于2^53-1的整数将Map到相同的值。因此,我们丢弃11位,然后将结果乘以1 / 2^53,得到在0..1范围内的均匀分布,得到0的概率是1 / 2^53(1 /9,007,199,254,740,992)。此实现比旧实现更好,因为在0..1范围内,它提供了更多不同的双精度值(2^53,而旧版本中为2^32)。
你还在评论中问:
如果知道0(包括0)和1(不包括1)之间有多少个数字(根据IEEE 754),就有可能回答“概率”问题,因为0是所有数字之一
事实并非如此。在IEEE 754中,在0..1之间实际上有超过2^53个可表示的数字。我们有52位尾数,然后有11位指数,其中一半是负指数。几乎所有负指数(大约是11位范围的一半)与尾数结合在一起,都会给出0..1范围内的不同值。
为什么我们不能使用IEEE允许我们生成随机数的完整的0..1范围?因为这个范围是不均匀的(就像完整的双精度范围本身是不均匀的)。例如,在0..0.5范围内比在0.5..1范围内有更多的可表示数。
bgtovc5b2#
这是从一个严格的学术Angular 。
从Double Struct开始:
所有浮点数的有效位数也都有限,这也决定了浮点值近似实数的精确度。Double值的精度最高可达15位小数,但内部最多保留17位。这意味着某些浮点运算可能缺少更改浮点值所需的精度。
如果只有15位小数有效,则可能的返回值为:
收件人:
换句话说,你有
10^15
个可能的(相对不同的,"不同的")值(参见第一个答案中的Permutations):零只是这些可能性之一:
以百分比表示:
我想这是你能得到的最接近"正确"的答案...
......它在实践中是否以这种方式执行可能是另一个故事。
14ifxucb3#
只需要创建一个简单的程序,让它运行,直到你对尝试的次数感到满意为止。(参见:https://onlinegdb.com/ij1M50gRQ)
示例输出:
将
d
的值四舍五入为2位小数将返回0.5%