简体   繁体   English

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

[英]Why does the .Net implementation of Random.Next(int, int) require maxValue >= minValue?

While making a method to place a newly created form on a completely random location on my screen without going outside the bounds of said screen i had an interesting code contracts message stating... 在制定一种将新创建的表单放置在我的屏幕上完全随机的位置而不会超出所述屏幕范围的方法时,我有一条有趣的代码合同消息,说明...

contract requires unproven minValue <= maxValue 合同需要未经证实的minValue <= maxValue

... while using the code: ...在使用代码时:

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

Having looked at the .Net implementation i am baffled. 看完.Net的实现我很困惑。

My question is, why couldn't they simply swap the arguments around when max value is < minvalue. 我的问题是, 为什么当max value <minvalue时,他们不能简单地交换参数。
Is there any (beyond maybe not catching the obscure bug) reason as to why one shouldn't allow Random.Next(100, 50)? 关于为什么不应该允许Random.Next(100,50)的任何原因(可能未捕获到晦涩的错误)?

It shouldn't make any difference if you say "give me a random number between 100 (exclusive) and 50 (inclusive)" and "... between 50 (inclusive) and 100 (exclusive)". 如果您说“给我一个介于100(含)和50(含)之间的随机数”和“ ...介于50(含)和100(不含)之间的随机数”,则没有任何区别。
The range of numbers would still be the same wouldn't it? 数字的范围还是一样的,不是吗?

And that is before one considers the pitfalls with Random.Next(1, 2) and Random.Next(1, 1), both of which are perfectly valid code without any warnings. 而且这是在使用Random.Next(1,2)和Random.Next(1,1)考虑陷阱之前,这两个都是完全有效的代码,没有任何警告。 Both return 1 on every new generation and actually should warn the user about this behavior. 两者在每个新一代产品上都返回1,实际上应该警告用户这种行为。

EDIT An example of a potential pitfall when calling Random.Next(20, 20). 编辑调用Random.Next(20,20)时潜在陷阱的示例。

If you assume in your code that providing an upper bound of 20 will always give you random numbers between lower and 19 and your lower bound is allowed to go to 20 inclusive you, in this particular case, would potentially break your code when the lower bound hits 20 as that is the one case that Random.Next would return 20. Imagine you have some code with the upper bound in the millions, it might take some time before you suddenly run into that edge case. 如果您在代码中假设上限为20,则始终会为您提供介于下限和19之间的随机数,并且您的下限允许为20(含20)(包括在内),在这种情况下,当下限达到上限时,可能会破坏您的代码命中20,因为那是Random.Next将返回20的一种情况。想象一下,您有一些上限为百万的代码,突然遇到这种情况可能要花费一些时间。 At least it IS documented. 至少是有记载。

I am already aware of this question: Why can minValue == maxValue in Random.Next? 我已经知道了这个问题: 为什么在Random.Next中minValue == maxValue?

The answer is most likely "they could have, but they didn't". 答案很可能是“他们可能有,但他们没有”。

Programming languages and libraries are full of quirks like this, except that what you consider a quirk, others may call a design decision :-) 编程语言和库充满了这样的怪癖,除了您认为的怪癖外,其他人可能会称为设计决策:-)

It would make little sense to provide a function that took a minimum and maximum value which then proceeded to give you a value outside the scope of what you asked for. 提供一个带有最小值和最大值的函数,然后又为您提供超出您要求范围的值,这毫无意义。 Fair enough if the parameters were something like limit1/limit2 or one_end/the_other_end but, in any situation where the very definition of the values are contained in the name (such as min/max or upper/lower ), you're best off following certain guidelines, such as the principle of least astonishment . 如果参数是limit1/limit2one_end/the_other_end类的参数,就足够公平了,但是,在名称中包含值的确切定义的任何情况下(例如min/maxupper/lower ),您最好执行以下操作某些准则,例如最小惊讶原则

All the behaviour you're discussing is well-documented, it's not like it's a bug (if the doco was wrong) or even gray (if the doco didn't mention it). 您正在讨论的所有行为都有据可查,这并不是一个错误(如果doco错误)或什至是灰色(如果doco没有提及)。 It's plainly spelled out for all to read and take note of: 明确说明了所有内容,以供阅读和注意:

minValue : The inclusive lower bound of the random number returned. minValue :返回的随机数的包含性下限

maxValue : The exclusive upper bound of the random number returned. maxValue :返回的随机数的排他上限 maxValue must be greater than or equal to minValue . maxValue 必须大于或等于minValue

Return Value: A 32-bit signed integer greater than or equal to minValue and less than maxValue ; 返回值: 大于或等于minValue且小于maxValue 32位有符号整数; that is, the range of return values includes minValue but not maxValue . 也就是说,返回值的范围包括minValue而不是maxValue If minValue equals maxValue , minValue is returned. 如果minValue等于maxValue ,则返回minValue

If you really want a reversible range, there's nothing stopping you from doing it yourself, with something like (pseudo-code): 如果您确实想要一个可逆范围,可以使用(pseudo-code)之类的东西阻止您自己进行操作:

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

The only tricky bit is how you handle inclusive/exclusive at either end. 唯一棘手的一点是您如何处理两端的包容性/独占性。 In the example above, I've chosen to have the higher number exclusive no matter what. 在上面的示例中,无论如何,我都选择了较高的独占数。 If you want to have the second parameter exclusive, you'll need a slight change. 如果您想让第二个参数互斥,则需要稍作更改。


In any case, based on your code, you seem to be wanting to place a corner of some object so that the entire object falls within the target bounds. 无论如何,根据您的代码,您似乎想要放置某个对象的一个​​角,以使整个对象都落在目标范围之内。 If that's the case, the behaviour you desire is exactly the thing you want to avoid. 如果是这样的话,你想要的行为正是你希望避免的事情。

If the width of your object was for some reason greater than the width of the target bounds, it would place you object outside of the boundary (and, of course, if it's not greater, you have no problem anyway since the arguments to .Next() will be fine). 如果您的对象的宽度由于某种原因大于目标边界的宽度,则会将您的对象放置在边界之外 (当然,如果不大 ,则由于.Next()的参数,您也没有问题.Next()可以)。

To illustrate (we'll only cover left/right boundaries here but top/bottom is similar), assume you target boundaries are left=100 and right=200 . 为了进行说明(这里我们仅覆盖左/右边界,但顶部/底部类似),假设您的目标边界为left=100right=200 If the width of your object is anything between 1 and 100 (a) , it will work fine, and the object will be fully contained. 如果对象的宽度在1100 (a)之间 ,则可以正常工作,并且可以完全容纳对象。

If the object decides to fatten up a bit to 150 (for example), then the left side of it will fall somewhere between 50 and 100 , well outside the permissible boundaries. 例如,如果对象决定将其增加一点到150,则其左侧将落在50100之间的某个位置,远远超出允许的范围。


(a) There may be subtle edge cases at the boundary points caused by Jedi errors (Obi Wan = OB1 = off-by-one, get it?) but I'm discounting that for simplicity. (一)可能是微妙的边缘的情况下,在造成绝地错误的边界点(欧比旺= OB1 =断接一个,明白了吗?),但我贴现,为了简化。

I find this question to be rather bizarre. 我觉得这个问题很奇怪。

My question is, why couldn't they simply swap the arguments around when max value is < minvalue. 我的问题是,为什么当max value <minvalue时,他们不能简单地交换参数。

The parameters are called mixValue and manValue . 这些参数称为mixValuemanValue If you passed a value of 7 for minValue and 3 for maxValue , and it returned a value of 4, this would be completely shocking and undesirable behavior. 如果您为minValue传递了7的值,为maxValue传递了3的值,并且它返回的值为4,则这将是完全令人震惊的行为。 There is no value greater than or equal to 7 and less than or equal to 3, so all the method can do is throw an exception. 没有大于或等于7且小于或等于3的值,因此该方法所能做的就是抛出异常。

They could have instead called the parameters oneValue and otherValue , and ensured that the result was between, but I don't think there's anything strange about having a method that takes specify a range of numerical values in increasing order; 他们可以改为调用参数oneValueotherValue ,并确保结果介于两者之间,但我认为使用一种以递增顺序指定一系列数值的方法并不奇怪。 this is quite common. 这很普遍。 (And I don't think it's an unreasonable demand, either). (而且我也不认为这是不合理的需求)。

And in any case, two different inputs to the same method call resulting in the same output just doesn't sit right with me 在任何情况下,同一个方法调用的两个不同输入导致相同的输出只是不适合我

Why? 为什么? Math.Floor() will produce 3 for the inputs 3.04 , 3.99997 , and several trillion other inputs. Math.Floor()将产生3用于输入3.043.99997等几个兆输入。 There is nothing wrong with a method producing the same output for different inputs. 对于不同的输入产生相同的输出的方法没有错。 This, too, is quite a common situation. 这也是非常普遍的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM