提问人:xandor19 提问时间:9/28/2023 最后编辑:xandor19 更新时间:9/29/2023 访问量:49
在 Scala 中具有自定义比较的 Double 类型
Double type with custom comparation in Scala
问:
我正在将一些旧的 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 3.2
答:
4赞
Dima
9/28/2023
#1
最简单的方法可能是使用一组不同的运算符:
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
评论
0赞
Tim
9/28/2023
定义新运算符是个好主意,但 OP 现在表示这是 Scala 3,所以应该是而不是 .extension
implicit class
0赞
Dima
9/28/2023
这在 scala 3 中按原样工作正常。就个人而言,我不喜欢仅仅为了玩语法而玩弄版本之间的语言语法......因此,我将实时将其转换为更高级的风格,该风格在早期版本中无法编译,作为读者的练习:D
1赞
Tim
9/29/2023
#2
以下是在 Scala 3 中添加新的比较运算符的方法:
extension (d: Double)
def === (other: Double) = CompareDouble.equals(d, other)
def >> (other: Double) = CompareDouble.greater(d, other)
如果需要在 Scala 2 项目中使用它,则可以使用 in。CrossVersion.for2_13Use3
sbt
评论
Double
BigDecimal