在scala中警告或避免整数除法(导致截断)

时间:2019-04-04 22:32:56

标签: scala

考虑

 1 / 2

 val x: Int = ..
 val n: Int = ..

 x / n

这两个都等于.. 0 ..,因为整数除法会导致截断。

也:(这是我的典型用例):

val averageListSize =  myLists.map(_.length).sum()/myLists.length

在长时间计算的中间发生时,这已经使我痛苦了几次:第一个冲动是检查引入了哪些逻辑错误。只有经过一段时间的调试和头部抓挠之后,真正的罪魁祸首才出现。

有什么方法可以更清楚地揭示这种行为-例如是警告还是某种(对于我而言不为人所知)的语言设置或构造可能会警告或避免这种间歇性情况?

3 个答案:

答案 0 :(得分:3)

据我所知,Scala编译器似乎未提供警告标志,可能使您提出警告(文档here)。

但是,如果您发现值得付出的努力,则可以使用Scalafix并编写自己的自定义规则来检测整数除法并报告有关此警告。

以下是可以检测整数文字上的整数除法的规则的简短示例:

import scalafix.lint.{Diagnostic, LintSeverity}
import scalafix.patch.Patch
import scalafix.v1.{SemanticDocument, SemanticRule}

import scala.meta.inputs.Position
import scala.meta.{Lit, Term}

class IntDivision extends SemanticRule("IntDivision") {

  override def fix(implicit doc: SemanticDocument): Patch =
    doc.tree.collect({
      case term @ Term.ApplyInfix((_: Lit.Int, Term.Name("/"), Nil, _: List[Lit.Int])) =>
        Patch.lint(new Diagnostic {
          override final val severity: LintSeverity = LintSeverity.Warning
          override final val message: String = "Integer division"
          override final val position: Position = term.pos
        })
    }).asPatch

}

在以下代码段上运行时:

object Main {
  def main(args: Array[String]): Unit = {
    println(1 / 2)
  }
}

Scalafix将产生以下警告:

[warn] /path/to/Main.scala:3:13: warning: [IntDivision] Integer division
[warn]     println(1 / 2)
[warn]             ^^^^^

答案 1 :(得分:1)

If the / op doesn't work for you, make one that does.

implicit class Divider[N](numer :N)(implicit evN :Numeric[N]) {
  def /![D](denom :D)(implicit evD :Numeric[D]) :Double =
    evN.toDouble(numer) / evD.toDouble(denom)
}

testing:

1   /! 2    //res0: Double = 0.5
5.2 /! 2    //res1: Double = 2.6
22  /! 1.1  //res2: Double = 20.0
2.2 /! 1.1  //res3: Double = 2.0

答案 2 :(得分:0)

任何除法运算都可能导致截断或舍入。这在Int中最明显,但在所有数字类型(例如1.0/3.0)中都可能发生。所有数据类型的范围和准确性都受到限制,因此可以调整任何计算结果以适合结果数据类型。

目前尚不清楚在Int划分的特定情况下添加警告是否会有所帮助。无法捕获所有此类问题,在某些情况下发出警告可能会导致错误的安全感。对于完全有效的代码,它还会引起很多警告。

解决方案是仔细查看程序中的所有计算,并注意每个操作的范围和精度限制。如果涉及到任何严肃的计算,最好在数值分析中获得基础知识。