Scala除以零会产生不同的结果

时间:2017-05-12 13:00:12

标签: java scala arithmetic-expressions divide-by-zero

我对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

正如您在上面的示例中所看到的,根据您除以零的方式,您将获得以下其中一项:

  • “java.lang.ArithmeticException:/ by zero”
  • “Double = NaN”
  • “Double = Infinity”

这使得调试非常具有挑战性,尤其是在处理未知特征的数据时。这种方法背后的原因是什么,甚至更好的问题,如何在Scala中统一处理除零?

2 个答案:

答案 0 :(得分:3)

DoublesFloatsfloating-point个值(more here),可以表示为+Infinity -InfinityNaN as在IEEE 754标准中定义。
Integersfixed numbers,无法明确指出无效数据,因此会抛出exceptions
对此的统一解决方案是在getOrElse

上使用Try方法
Try(x/y).getOrElse(0)

如果您只想在ArithmeticException上恢复,可以使用recoverget

Try(x/y).recover{ case _: ArithmeticException => 0 }.get

recover可让您将Failure转换为Success
您也可以使用TryOption返回"无结果"没有显示异常

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