Как сравнить значения с плавающей запятой в Scala?
Насколько я знаю, точное сравнение не имеет особого смысла с значениями с плавающей запятой, поскольку то, что должно быть 0.0001, может быть чем-то вроде 0.0001000... 0001... Должен ли я реализовать свою собственную функцию сравнения, чтобы указать точность или существует ли распространенная практика для этого?
Раньше я использовал С# (который, я подозреваю, по-прежнему ошибочен, так как двойное значение может быть, вероятно, непригодным для представления 0.0001 вообще, даже задано как константа (как объяснил Майкл Боргвардт здесь)):
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;
}
Должен ли я что-то делать в Scala?
Ответы
Ответ 1
Да, вы можете сделать то же самое, что и в Java. Вы также можете использовать некоторые из Scala классных функций и сутровать Double Class с помощью метода ~ =, который принимает неявный параметр точности, который нужно только указать один раз.
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
Ответ 2
Или с помощью 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
}
Ответ 3
Использование Толерантность от scalautils
import org.scalautils._
import TripleEquals._
import Tolerance._
val result = 2.000001
результат: Double = 2.000001
result === 2.0 +- .001
res0: Boolean = true
result === 2.0 +- .000000001
res1: Boolean = false
Обновление: для Scala 2.11
import org.scalatest._
import org.scalatest.Matchers._
val r = 4
val rr = (r === 2 +- 1)
r: Int = 4
rr: Boolean = false