【问题标题】:Why does the .Net implementation of Random.Next(int, int) require maxValue >= minValue?为什么 Random.Next(int, int) 的 .Net 实现需要 maxValue >= minValue?
【发布时间】:2014-12-09 02:31:34
【问题描述】:

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

合约需要未经证实的 minValue

...在使用代码时:

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

看了.Net implementation我很困惑。

我的问题是,为什么当最大值为
是否有任何原因(除了可能没有发现晦涩的错误)为什么不应该允许 Random.Next(100, 50)?

如果您说“给我一个介于 100(不含)和 50(含)之间的随机数”和“...介于 50(含)和 100(不含)之间”,这应该没什么区别。
数字的范围还是一样的,不是吗?

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

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

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

我已经知道这个问题了:Why can minValue == maxValue in Random.Next?

【问题讨论】:

  • 答案是“他们可以拥有,但他们没有”。编程语言和库充满这样的怪癖,除了你认为是怪癖,其他人可能称之为设计决策 :-) 你讨论的所有行为都有据可查,它不像这是一个错误(如果 doco 是错误的)甚至是灰色的(如果 doco 没有提到它)。它清楚地说明了所有人都可以阅读和注意。
  • 添加到 @paxdiablo ,他们可能会这样做以保留 .Net 框架中的一些早期实现。简而言之,不要破坏一些早期内部实现的功能。
  • 我非常高兴他们没有这样做。如果我将某些东西传递给名为“minValue”的参数,我希望该方法将其视为最小值。它直观且有意义,给您一个明确的期望。如果参数是“oneExtreme”和“theOtherExtreme”,那么可以,但不是。
  • 实际上,我想扩展我的评论,但我变得如此冗长和喋喋不休(今天的词,技术上不正确,但自从凯撒使用这个词以来,我就喜欢这个词它在 Asterix 漫画中)只适合答​​案:-)

标签: c# .net random


【解决方案1】:

答案很可能是“他们可以有,但他们没有”。

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

提供一个取最小值和最大值然后继续为您提供一个值超出您所要求的范围的函数是没有意义的。如果参数类似于 limit1/limit2one_end/the_other_end 就足够公平了,但是在名称中包含值的定义的任何情况下(例如 min/maxupper/lower),您最好关注某些准则,例如principle of least astonishment

您所讨论的所有行为都有据可查,它不像是错误(如果文档有误)甚至是灰色(如果文档没有提及)。 plainly spelled out 供大家阅读和注意:

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

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

返回值:一个32位有符号整数大于或等于minValue且小于maxValue;即返回值的范围包括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,明白了吗?)但为简单起见,我将其打折。

【讨论】:

  • 我觉得我应该将此标记为答案,但它并没有真正回答我的问题,这就是为什么他们决定施加此限制。我的原始代码有潜在的缺陷(我已经修复,它是我的测试代码的一部分)不适合我的屏幕范围并不重要。我的原始代码可以在那种边缘情况下工作,它只会将新表单放在 -(boundWidth - formWidth) 到左边界区域的某个位置。
  • @Cadde 关于为什么某些框架实现者做出某些设计决策的问题在 Stack Overflow 上是题外话。在大多数情况下,实施者不是来回答这些问题的,而且决定背后的原因可能不会公开。我们能做的最好的就是解释为什么这是一个体面的设计决策,而基于意见的这一点在这里又是题外话了。
  • @JLRishe 我不仅在寻找设计师为什么这样做的答案,而且在框架设计之外是否有一些好的理由来解释为什么会这样。为了只做一个扩展方法或者说重载允许参数顺序在任何配置中的随机类。
  • @Cadde,对不起,我以为我已经在“设计决策”段落中说清楚了。我将对此进行一些扩展。
【解决方案2】:

我觉得这个问题很奇怪。

我的问题是,为什么他们不能在最大值为

参数称为mixValuemanValue。如果您为minValue 传递了7 的值,为3 传递了maxValue 的值,并且它返回了一个值4,这将是完全令人震惊和不受欢迎的行为。没有大于等于 7 小于等于 3 的值,所以方法只能抛出异常。

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

在任何情况下,同一个方法调用的两个不同输入导致相同的输出只是不适合我

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

【讨论】:

  • Math.Floor 的好点子。其他示例包括 %、散列函数和许多其他的,要么太多而无法提及,要么比我开始评论时最初想象的要少得多,现在我被困住了 :-)
  • 这是有道理的,我不认为他们专门这样称呼参数 min 和 max 。我的思绪更多地锁定在他们不允许价值观按任何顺序排列的事实上。因此也称他们为oneValueotherValue。至于不同的输入,我可以用不同的措辞。文档明确指出返回值小于 高于上限。所以,如果我想确定我不能得到一个大于 19 的值,不管我的下限是多少,那么我会说我的专属上限是 20,但是当我给它一个 20 的下限时......
  • @Cadde 啊,我明白你现在的意思了。上限是唯一的,除非两个值相同(并且文档的措辞不准确)。我同意你的看法,这是非常令人不安的行为。就个人而言,我认为如果上限总是包容性的会很有意义,但我只能假设实施者有他们的理由。
  • 我认为不一致是次要的,因为它都在一页上,您可以在返回值部分看到文本。我,一方面,认为返回值文本应该优先,但我同意它可能被误读。我已经为 MSDN 提出了建议,可以随意评论或投票:feedback.msdn.com/forums/257782-msdn-feature-suggestions/…
  • @paxdiablo 严格来说,返回值文本本身就是自相矛盾的。首先它说返回值小于maxValue,然后它说在某些情况下返回值可以等于maxValue。为了准确,它必须读取类似“如果 minValue 和 maxValue 不相等, 32 位有符号整数大于或等于 minValue 且小于maxValue;即返回值的范围包括minValue但不包括maxValue。如果minValue等于maxValue,则返回minValue。"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-03
  • 2015-12-08
  • 1970-01-01
  • 2016-04-10
  • 2021-07-16
  • 2016-05-30
相关资源
最近更新 更多