为什么scala在此模运算中返回超出范围的值?

时间:2015-01-31 12:21:14

标签: scala math random

这是一段代码,用于在给定范围内生成随机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
}

我知道这些结果并不统一,但对minmax的某些值无效,但这不是重点。

在测试结果中,以下断言并非总是如此:

getLong(-1L, 1L) >= -1L

更具体地说,返回值为-3。怎么可能呢?

1 个答案:

答案 0 :(得分:3)

事实证明,math.abs(x: Long): Long并不能保证始终返回非负值!没有Long值可以代表math.abs(Long.MinValue),因此math.abs不会抛出异常,而是返回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来测试至少部分代码库。