C# 随机浮点数闭区间

3
我很惊讶在任何地方都找不到答案,也许我错过了什么。 System.Random类的NextDouble方法返回[0.0,1.0)范围内的双精度浮点数。这是一个半开区间,返回0.0 <= x < 1.0
我需要一个闭区间[0.0,1.0],使得0.0 <= x <= 1.0。在C++中,我可以使用std::nextafter,它会返回大于所传参数的最小可表示浮点数(例如,std::nextafter(1.0, 2.0)会返回1.0000001192092895508)。我似乎找不到C#的等效方法。
我正在处理大量高精度数字(16位),因此即使1.0很少出现,我仍然需要它具备这种能力。虽然1.01.0000001192092895508之间的差异看起来微不足道(通常确实如此),但在这种情况下,这种差异是重要的。

在实现类似于this版本的NextAfter解决方案后,有时会得到超过最大值的数字(例如,[0.0,5.0]5.00000027008353

Random.NextDouble() * ((NextAfter(max, max + 1.0) - min) + min);

我该如何生成具有闭区间的随机浮点数?我将执行此操作多次,因此最好不要使用需要较长时间才能执行的方法(例如多次调用Random或使用while循环和拒绝抽样)。此外,必须是无偏的,产生均匀的结果(即任何一个数字出现的可能性都不应该比其他数字更高)。

这里有几个问题,但让我更好地理解一下,您想要在(包括)X和Y之间的随机浮点数(16位),尽可能随机,即尽可能少的偏差。 - TheGeneral
没错,如果必要的话,我可能会降级到8位。 - anon
MSDN表示:Random.NextDouble()方法返回的随机数的实际上限为0.99999999999999978。 - Prateek Shrivastava
1.0000001192092895508是(大约)在常见的IEEE-754基本32位二进制浮点格式中,紧随1后面的下一个32位浮点值。您是否指的是下一个64位值,即1.0000000000000002220446049250313080847263336181640625? - Eric Postpischil
2
然而,有一个问题,将NextDouble的结果转换为较窄的格式可能会产生不均匀版本。在像.125或.5这样的内部数字周围,存在一些宽度为w的间隔,其中所有数字都舍入到该数字。但是,在0和1处,只有宽度为½ w的间隔中的数字舍入为0或1,因此它们出现的频率比其他数字要少。您可能应该更全面地描述您的问题并要求完整的解决方案,而不仅仅是询问如何关闭NextDouble间隔。 - Eric Postpischil
显示剩余6条评论
2个回答

2

这似乎很简单:

  • 决定平均多久出现一次1.0。比如说,十亿次中有一次。
  • 从您选择的平均值为十亿的钟形分布中生成介于零和二十亿之间的随机整数。将其称为n。
  • 在开区间上生成n个随机数。
  • 生成1.0。
  • 重复。

现在,您有了一个随机数序列,其中1.0平均出现的次数符合预期。您每十亿次进行一次昂贵的钟形计算,这样就可以摊销基本为零的成本。


我不相信这是收敛于正态分布的分布之一。 - Ben Voigt
为了获得额外价值的独立同分布出现,需要使用几何分布:https://en.wikipedia.org/wiki/Geometric_distribution - Ben Voigt

0

浮点数的位表示意味着有限数量的不同值。确定可能的浮点数值,获取该范围内的随机整数,并将/转换此值映射到您的浮点数范围。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接