如何比较 Scala 中的浮点值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8385458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:43:51  来源:igfitidea点击:

How to compare floating point values in Scala?

scalacomparisonfloating-pointdouble

提问by Ivan

As far as I know, exact comparison doesn't make much sense with floating point values as what is intended to be 0.0001 can actually be something like 0.0001000...0001... Should I implement my own comparison function to specify precision or is there a common practice for this?

据我所知,精确比较对浮点值没有多大意义,因为 0.0001 实际上可能是 0.0001000...0001 之类的东西......我应该实现我自己的比较函数来指定精度还是对此有共同的做法吗?

I used to use the following with C# (which, I suspect, is still wrong as a Double value can be probably uncapable of representing 0.0001 at all, even set as a constant (as Michael Borgwardt explained here)):

我曾经在 C# 中使用以下内容(我怀疑这仍然是错误的,因为 Double 值可能根本无法表示 0.0001,甚至设置为常量(如 Michael Borgwardt在此处解释的那样)):

public static bool AlmostEquals(this double x, double y, double precision = 0.0001)
{
  if (precision < 0.0)
    throw new ArgumentException();

  return Math.Abs(x - y) <= precision;
}

Should I do something alike in Scala?

我应该在 Scala 中做类似的事情吗?

回答by Kim Stebel

Yes, you can do the same thing as in Java. You could also use some of Scala's cool features and pimp the Double class with a ~= method that takes an implicit precision parameter that only needs to be specified once.

是的,您可以执行与 Java 相同的操作。您还可以使用 Scala 的一些很酷的功能,并使用 ~= 方法对 Double 类进行皮条客,该方法采用隐式精度参数,只需指定一次。

scala> case class Precision(val p:Double)
defined class Precision

scala> class withAlmostEquals(d:Double) {
  def ~=(d2:Double)(implicit p:Precision) = (d-d2).abs <= p.p
}
defined class withAlmostEquals

scala> implicit def add_~=(d:Double) = new withAlmostEquals(d)
add_$tilde$eq: (d: Double)withAlmostEquals

scala> 0.0~=0.0
<console>:12: error: could not find implicit value for parameter p: Precision
              0.0~=0.0
                 ^

scala> implicit val precision = Precision(0.001)
precision: Precision = Precision(0.001)

scala> 0.0 ~= 0.00001
res1: Boolean = true

回答by Kim Stebel

Or with 2.10...

或者用 2.10 ...

case class Precision(p:Double)

implicit class DoubleWithAlmostEquals(val d:Double) extends AnyVal {
  def ~=(d2:Double)(implicit p:Precision) = (d - d2).abs < p.p
}

回答by Roman Zykov

Use Tolerance from scalautils

使用 scalautils 的容差

import org.scalautils._
import TripleEquals._
import Tolerance._

val result = 2.000001

result: Double = 2.000001

结果:双倍 = 2.000001

result === 2.0 +- .001

res0: Boolean = true

res0:布尔值 = 真

result === 2.0 +- .000000001

res1: Boolean = false

res1:布尔值 = 假

Update: For Scala 2.11

更新:对于 Scala 2.11

import org.scalatest._
import org.scalatest.Matchers._
val r = 4
val rr = (r === 2 +- 1)

r: Int = 4 
rr: Boolean = false