考虑
1 / 2
或
val x: Int = ..
val n: Int = ..
x / n
这两个都等于.. 0 ..,因为整数除法会导致截断。
也:(这是我的典型用例):
val averageListSize = myLists.map(_.length).sum()/myLists.length
在长时间计算的中间发生时,这已经使我痛苦了几次:第一个冲动是检查引入了哪些逻辑错误。只有经过一段时间的调试和头部抓挠之后,真正的罪魁祸首才出现。
有什么方法可以更清楚地揭示这种行为-例如是警告还是某种(对于我而言不为人所知)的语言设置或构造可能会警告或避免这种间歇性情况?
答案 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
划分的特定情况下添加警告是否会有所帮助。无法捕获所有此类问题,在某些情况下发出警告可能会导致错误的安全感。对于完全有效的代码,它还会引起很多警告。
解决方案是仔细查看程序中的所有计算,并注意每个操作的范围和精度限制。如果涉及到任何严肃的计算,最好在数值分析中获得基础知识。