在制作一种方法将新创建的表单放在我的屏幕上一个完全随机的位置而不超出所述屏幕的范围时,我有一个有趣的代码合同消息说明......
合同需要未经证实的minValue <= maxValue
...使用代码时:
Location = new Point(
this.rnd.Next(targetBounds.Left, targetBounds.Right - Width),
this.rnd.Next(targetBounds.Top, targetBounds.Bottom - Height));
Run Code Online (Sandbox Code Playgroud)
看了.Net实现后,我很困惑.
我的问题是,为什么他们不能简单地在最大值为<minvalue时交换参数.
有没有(除了可能没有捕捉到晦涩的错误)的原因,为什么一个人不应该允许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,因为这是Random.Next将返回20的一种情况.想象一下,你有一些上限为数百万的代码,可能需要一些时间才能突然遇到边缘情况.至少它是有记录的.
我已经意识到这个问题:为什么在Random.Next中minValue == maxValue?
答案很可能是"他们可以拥有,但他们没有".
编程语言和库充满了这样的怪癖,除了你认为是怪癖,其他人可能会称之为设计决定:-)
提供一个具有最小值和最大值的函数是没有意义的,然后继续为您提供超出所要求范围的值.如果参数是类似的,limit1/limit2或者one_end/the_other_end在任何情况下,如果值的定义包含在名称中(例如min/max或upper/lower),那么你最好遵循某些指导原则,例如最不惊讶的原则.
您正在讨论的所有行为都有详细记录,它不像是一个错误(如果doco错误)或者甚至是灰色(如果doco没有提到它).它清楚地阐明了所有人阅读和采取的注意事项:
minValue:返回的随机数的包含下限.
maxValue:返回的随机数的独占上限.maxValue必须大于或等于minValue.返回值:大于或等于
minValue且小于的maxValue32位有符号整数; 也就是说,返回值的范围包括minValue但不包括maxValue.如果minValue等于maxValue,minValue则返回.
如果你真的想要一个可逆的范围,没有什么能阻止你自己做这件事,比如(伪代码):
def revRandom (end1, end2):
if end1 > end2:
return realRandom (end2, end1)
return realRandom (end1, end2)
Run Code Online (Sandbox Code Playgroud)
唯一棘手的一点是你如何处理两端的包容性/独占性.在上面的例子中,无论如何,我都选择了更高的数字.如果你想让第二个参数独占,你需要稍作改动.
在任何情况下,根据您的代码,您似乎想要放置某个对象的角落,以便整个对象落在目标边界内.如果是这样的话,你想要的行为正是你想避免的事情.
如果你的对象的宽度由于某种原因大于目标边界的宽度,它会把你的对象放在边界之外(当然,如果它不是更大,你也没有问题,因为参数.Next()将是精细).
为了说明(我们只在这里覆盖左/右边界,但顶部/底部是相似的),假设您的目标边界是left=100和right=200.如果对象的宽度是1和100 (a)之间的任何值,它将正常工作,并且对象将被完全包含.
如果对象决定增肥位150(例如),那么它的左侧将某处掉下之间50和100,以及外面的容许界限.
(a)在Jedi错误造成的边界点可能存在微妙的边缘情况(Obi Wan = OB1 =一个接一个,得到它?)但是我为了简单起见而对此进行了折扣.
| 归档时间: |
|
| 查看次数: |
288 次 |
| 最近记录: |