Scala 中具有自定义比较的双精度类型

问题描述 投票:0回答:1

我正在将一些旧的 Java 代码迁移到 Scala,它使用“精度”阈值来比较实际值。已翻译为 Scala 代码的片段如下:

object CompareDouble {
  private val EPSILON = 0.00001

  def equals(a: Double, b: Double): Boolean = a == b || Math.abs(a - b) < EPSILON

  def greater(a: Double, b: Double): Boolean = a - b > EPSILON
  .
  .
  .
}

这段代码的问题在于它的用法很容易变得冗长,例如:

  //In an interval overlap comparison
        CompareDouble.lessEquals(low1, low2) && CompareDouble.lessEquals(low2, up1) ||
          CompareDouble.lessEquals(low1, up2) && CompareDouble.lessEquals(up2, up1) ||
          CompareDouble.lessEquals(low2, low1) && CompareDouble.lessEquals(low1, up2) ||
          CompareDouble.lessEquals(low2, up1) && CompareDouble.lessEquals(up1, up2)

所以我试图为允许我使用标准运算符的值定义某种包装类。这个想法是能够做到:

  //Just an example of the idea
  if a == b then...
  else if a > b then...

其中

a == b
是原始的
def equals(a: Double, b: Double):
等等

到目前为止,我已经做到了:

class PrecisionDouble(var wrapp: Double) {
  // PrecissionDouble.EPSILON refers to a field in this class' companion object
  def == (that: PrecisionDouble): Boolean = wrapp == that.wrapp || Math.abs(wrapp - that.wrapp) < PrecisionDouble.EPSILON

  def < (that: PrecisionDouble): Boolean = (that.wrapp - wrapp) > PrecisionDouble.EPSILON

这适用于比较用例,但我必须手动包装和解开类中的值以用于其他用途(例如数学函数或基本 aritmethics)。我想实现这个目标:

  val a = PrecisionDouble(3.2)
  val b: Double = math.sqrt(a)

并且还能够将 PrecisionDouble 比较方法中的参数类型从

def == (that: PrecisionDouble)
替换为
def == (that: Double)
,以便能够更加简洁地进行比较。

这有可能吗?

scala wrapper
1个回答
0
投票

最简单的可能是使用一组不同的运算符:

object Precision { 
   implicit class D(val d: Double) extends AnyVal { 
     def === (other: Double) = CompareDouble.equals(d, other)
     def >> (other: Double) = CompareDouble.grater(d, other)
     // etc.
   }
}

import Precision._

println (1.41 === math.sqrt(2))

或者,您可以在

Double
PrecisionDouble
之间定义隐式转换,但我认为,这是较差的,因为,如果运算符相同,则在大多数情况下转换都不会自动发生。

© www.soinside.com 2019 - 2024. All rights reserved.