[英]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
正如您在上面的示例中所看到的,取决于您如何除以零,您将获得以下之一:
这使得调试非常具有挑战性,尤其是在处理未知特征的数据时。 这种方法背后的原因是什么,甚至更好的问题,如何在Scala中以统一的方式处理除零?
各种类型的零规则都归结为除法。
0 / 0
是整数除零 (因为两个参数都是整数文字),并且需要抛出java.lang.ArithmeticException
。
1.toDouble/0.toDouble
是一个浮点除零 ,带有正分子,需要求值为+Infinity
。
0.0/0.0
是浮点除以零,分子为零,需要求值为+NaN
。
第一个是Java和Scala约定,另外两个是IEEE754浮点的属性,这是Java和Scala都使用的。
Doubles
和Floats
是floating-point
值( 更多在这里 ),其可以被表示为+Infinity
-Infinity
和NaN
限定如IEEE 754标准。
Integers
是fixed numbers
,没有任何明确指示无效数据的方法,因此它们会抛出exceptions
对此的统一解决方案是在Try
上使用getOrElse
方法
Try(x/y).getOrElse(0)
如果您只想在ArithmeticException
recover
,可以使用recover
和get
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.