繁体   English   中英

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

[英]Scala division by zero yields different results

我对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”
  • “双= NaN”
  • “Double = Infinity”

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

各种类型的零规则都归结为除法。

0 / 0整数除零 (因为两个参数都是整数文字),并且需要抛出java.lang.ArithmeticException

1.toDouble/0.toDouble是一个浮点除零 ,带有正分子,需要求值为+Infinity

0.0/0.0是浮点除以零,分子为零,需要求值为+NaN

第一个是Java和Scala约定,另外两个是IEEE754浮点的属性,这是Java和Scala都使用的。

DoublesFloatsfloating-point值( 更多在这里 ),其可以被表示为+Infinity -InfinityNaN限定如IEEE 754标准。
Integersfixed numbers ,没有任何明确指示无效数据的方法,因此它们会抛出exceptions
对此的统一解决方案是在Try上使用getOrElse方法

Try(x/y).getOrElse(0)

如果您只想在ArithmeticException recover ,可以使用recoverget

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

recover允许您将Failure转换为Success
您还可以使用Try to Option返回“无结果”而不显示异常

Try(x/y).toOption

你可以使用部分函数来做这样的事情。 例如:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM