我对Scala处理除零的方式感到困惑。这是一个REPL代码片段。
scala> 1/0
java.lang.ArithmeticException: / by zero
... 33 elided
scala> 1.toDouble/0.toDouble
res1: Double = Infinity
scala> 0.0/0.0
res2: Double = NaN
scala> 0/0
java.lang.ArithmeticException: / by zero
... 33 elided
scala> 1.toInt/0.toInt
java.lang.ArithmeticException: / by zero
... 33 elided
正如您在上面的示例中所看到的,根据您除以零的方式,您将获得以下其中一项:
这使得调试非常具有挑战性,尤其是在处理未知特征的数据时。这种方法背后的原因是什么,甚至更好的问题,如何在Scala中统一处理除零?
答案 0 :(得分:3)
Doubles
和Floats
为floating-point
个值(more here),可以表示为+Infinity
-Infinity
和NaN
as在IEEE 754标准中定义。
Integers
为fixed numbers
,无法明确指出无效数据,因此会抛出exceptions
对此的统一解决方案是在getOrElse
Try
方法
Try(x/y).getOrElse(0)
如果您只想在ArithmeticException
上恢复,可以使用recover
和get
Try(x/y).recover{ case _: ArithmeticException => 0 }.get
recover
可让您将Failure
转换为Success
您也可以使用Try
至Option
返回"无结果"没有显示异常
Try(x/y).toOption
答案 1 :(得分:1)
你可以使用部分功能来做这样的事情。例如:
object MyObject {
def main(args: Array[String]) {
println(safeDiv.isDefinedAt(1.0, 1.0)) // true
println(safeDiv.isDefinedAt(1.0, 0.0)) // false
println(safeDiv(1.0, 1.0)) // 1.0
println(safeDiv(1.0, 0.0)) // crash
}
def safeDiv: PartialFunction[(Double, Double), Double] = {
case(a,b) if b != 0.0 => a/b
}
}
部分函数允许您检查是否为给定输入定义了函数。在上面的例子中,我说如果除数是0.0,则不定义函数safeDiv
。因此,您可以检查函数是否将在给定输入的情况下执行。检查不是必需的,但safeDiv(1.0, 0.0)
将不会执行。
部分功能是你的朋友反对这样的事情:
scala> (1.0/0.0).toInt
res22: Int = 2147483647