为什么 scala return 在此模运算中超出范围值?
Why does scala return an out of range value in this modulo operation?
这是一段在给定范围内生成随机 Long 值的代码,为清楚起见进行了简化:
def getLong(min: Long, max: Long): Long = {
if(min > max) {
throw new IncorrectBoundsException
}
val rangeSize = (max - min + 1L)
val randValue = math.abs(Random.nextLong())
val result = (randValue % (rangeSize)) + min
result
}
我知道这不是统一的结果,对于 min
和 max
的某些值,这将无法正常工作,但这不是重点。
在测试中证明,以下断言并不总是正确的:
getLong(-1L, 1L) >= -1L
更具体地说,返回值为 -3
。这怎么可能?
事实证明,math.abs(x: Long): Long
不能保证总是 return 非负值!没有可以表示 math.abs(Long.MinValue)
的 Long
值,因此不会抛出异常,而是 math.abs
returns Long.MinValue
:
scala> Long.MinValue
res27: Long = -9223372036854775808
scala> math.abs(Long.MinValue)
res28: Long = -9223372036854775808
scala> math.abs(Long.MinValue) % 3
res29: Long = -2
scala> math.abs(Long.MinValue) % 3 + (-1)
res30: Long = -3
在我看来,这是一个很好的例子,说明为什么应该使用 ScalaCheck 来测试至少部分代码库。
这是一段在给定范围内生成随机 Long 值的代码,为清楚起见进行了简化:
def getLong(min: Long, max: Long): Long = {
if(min > max) {
throw new IncorrectBoundsException
}
val rangeSize = (max - min + 1L)
val randValue = math.abs(Random.nextLong())
val result = (randValue % (rangeSize)) + min
result
}
我知道这不是统一的结果,对于 min
和 max
的某些值,这将无法正常工作,但这不是重点。
在测试中证明,以下断言并不总是正确的:
getLong(-1L, 1L) >= -1L
更具体地说,返回值为 -3
。这怎么可能?
事实证明,math.abs(x: Long): Long
不能保证总是 return 非负值!没有可以表示 math.abs(Long.MinValue)
的 Long
值,因此不会抛出异常,而是 math.abs
returns Long.MinValue
:
scala> Long.MinValue
res27: Long = -9223372036854775808
scala> math.abs(Long.MinValue)
res28: Long = -9223372036854775808
scala> math.abs(Long.MinValue) % 3
res29: Long = -2
scala> math.abs(Long.MinValue) % 3 + (-1)
res30: Long = -3
在我看来,这是一个很好的例子,说明为什么应该使用 ScalaCheck 来测试至少部分代码库。