Java Scala除以零会产生不同的结果
我对Scala如何处理零除法感到困惑。下面是一个REPL代码片段Java Scala除以零会产生不同的结果,java,scala,arithmetic-expressions,divide-by-zero,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
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.arithmetricException:/by zero”
- “Double=NaN”
- “Double=无穷大”
这使得调试非常具有挑战性,尤其是在处理未知特征的数据时。这种方法背后的原因是什么,甚至是一个更好的问题,即如何在Scala中以统一的方式处理零除法?这完全取决于各种类型的零除法规则
0/0
是一个整数除以零(因为两个参数都是整数文本),这是抛出java.lang.arithmetricException
所必需的
1.toDouble/0.toDouble
是一个带正分子的浮点除以零,计算为+无穷大
0.0/0.0
是一个用零分子除以零的浮点数,计算为+NaN
第一个是Java和Scala约定,另外两个是IEEE754浮点的属性,这是Java和Scala都使用的。
双精度
和浮点
是浮点值()可表示为标准中定义的+无限
-无限
和NaN
。
整数
是固定数字
,它们没有任何方式明确表示无效数据,因此它们抛出异常
对此的统一解决方案是在Try
上使用getOrElse
方法
Try(x/y).getOrElse(0)
如果只想在算术异常
上恢复,可以使用恢复
和获取
Try(x/y).recover{ case _: ArithmeticException => 0 }.get
恢复
允许您将故障
转换为成功
您还可以使用Try
to选项
在不显示异常的情况下返回“无结果”
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
我认为这与不同的数据类型有关。当执行不同但相关的计算时,请尝试始终使用相同的数据类型。例如:Double,Int,etcYou可能正在处理未知特征的数据,但在Scala这样的静态类型语言中,您并不是在处理未知类型的数据。@AlexeyRomanov我理解您的意思。不过,我想大多数人都会同意,这种方法容易出现一些非常肮脏的bug,而且在您编写的每一个算术运算中都非常繁琐。谢谢。你的回答很有帮助,因为它详细说明了可能的解决方案。我发现Try(1.0/0.0)
将返回Success(Infinity)
而不是Failure
,并且OrElse
不会返回。太好了。我想它会变得很方便