为什么 Random.Next(int, int) 的 .Net 实现需要 maxValue >= minValue

本文关键字:int maxValue minValue 实现 Next Random 为什么 Net | 更新日期: 2023-09-27 18:33:41

在制作一种方法将新创建的表单放置在屏幕上完全随机的位置而不超出所述屏幕的范围时,我有一个有趣的代码合约消息,指出...

合约需要未经证实的最小值 <= 最大值

。使用代码时:

        Location = new Point(
            this.rnd.Next(targetBounds.Left, targetBounds.Right - Width),
            this.rnd.Next(targetBounds.Top, targetBounds.Bottom - Height));

看了 .Net 实现后,我很困惑。

我的问题是为什么当最大值<最小值时,他们不能简单地交换参数。>
是否有任何(除了可能没有抓住晦涩的错误(理由来说明为什么不应该允许 Random.Next(100, 50(?

如果您说"给我一个介于 100(不包括(和 50(含(之间的随机数"和"......介于 50(含(和 100(不含(之间"。
数字的范围仍然是一样的,不是吗?

这是在考虑 Random.Next(1, 2( 和 Random.Next(1, 1( 的陷阱之前,两者都是完全有效的代码,没有任何警告。两者都在每一代新世代上返回 1,实际上应该警告用户此行为。

编辑 调用 Random.Next(20, 20( 时的潜在陷阱示例。

如果您在代码中假设提供 20 的上限将始终为您提供介于下限和 19 之间的随机数,并且您的下限允许达到 20(包括 20(,那么在这种特殊情况下,当下限达到 20 时,可能会破坏您的代码,因为这是 Random.Next 将返回 20 的一种情况。想象一下,您有一些上限为数百万的代码,可能需要一些时间才能突然遇到这种边缘情况。至少它是有记录的。

我已经知道这个问题:为什么 minValue == maxValue in Random.Next?

为什么 Random.Next(int, int) 的 .Net 实现需要 maxValue >= minValue

答案很可能是"他们本可以,但他们没有"。

编程语言和库充满了这样的怪癖,除了你认为的怪癖,其他人可能会称之为设计决策:-(

提供一个取最小值和最大值的函数是没有意义的,然后继续给你一个超出你要求范围的值。如果参数是limit1/limit2one_end/the_other_end之类的东西,那就很公平了,但是,在名称中包含值定义的任何情况下(例如min/maxupper/lower(,您最好遵循某些准则,例如最小惊讶原则。

您正在讨论的所有行为都有据可查,它不像是一个错误(如果 doco 是错误的(甚至灰色的(如果 doco 没有提到它(。它清楚地拼写出来供所有人阅读和注意:

minValue:返回的随机数的包含限。

maxValue:返回的随机数的独占上限maxValue必须大于或等于 minValue

返回值:大于等于minValue且小于maxValue的32位有符号整数;即返回值的范围包括minValue但不包括maxValue如果minValue等于 maxValue ,则返回minValue

如果你真的想要一个可逆的范围,没有什么能阻止你自己做,比如(伪代码(:

def revRandom (end1, end2):
    if end1 > end2:
        return realRandom (end2, end1)
    return realRandom (end1, end2)

唯一棘手的一点是你如何处理两端的包容性/排他性。在上面的例子中,无论如何,我都选择将较高的数字排除在外。如果要使第二个参数独占,则需要稍作更改。

<小时 />

无论如何,根据您的代码,您似乎想要放置某个对象的一角,以便整个对象落在目标边界内。如果是这样的话,你想要的行为正是你想要避免的。

如果对象的宽度由于

某种原因大于目标边界的宽度,它会将对象置于边界之外(当然,如果它大,无论如何您都没有问题,因为.Next()的参数会很好(。

为了说明(我们在这里只介绍左/右边界,但顶部/底部是相似的(,假设你的目标边界是left=100right=200。如果对象的宽度介于 1100 (a( 之间,则它可以正常工作,并且对象将被完全包含。

例如,如果物体决定增肥一点到150,那么它的左侧将落在50100之间,远远超出允许的边界。

<小时 />(

a(在边界点上可能存在由绝地错误引起的微妙边缘情况(Obi Wan = OB1 = off-by-one,明白吗?(,但为了简单起见,我对此打了折扣。

我觉得这个问题很奇怪。

我的问题是,为什么当最大值<最小值时,他们不能简单地交换参数。>

这些参数称为 mixValuemanValue 。如果您为 minValue 传递了值 7,为 maxValue 传递了 3 的值,并且它返回了值 4,这将完全令人震惊和不良的行为。没有大于或等于 7 且小于或等于 3 的值,因此该方法所能做的就是抛出异常。

他们本可以调用参数oneValueotherValue,并确保结果介于两者之间,但我认为有一个方法以递增的顺序指定一系列数值并不奇怪; 这是很常见的。(我也不认为这是一个不合理的要求(。

无论如何,同一方法调用的两个不同输入导致相同的输出对我来说是不合适的

为什么? Math.Floor()将为3.043.99997和数万亿其他输入产生3。为不同的输入生成相同输出的方法没有错。这也是一种很普遍的情况。