在 groovy/grails 中的 BigDecimal 上使用比较运算符是否安全?

Joh*_*tle 5 comparison groovy bigdecimal operator-keyword

Java 比较两个 BigDecimal 的方法是使用 compareTo() 方法,并检查结果是 -1、0 还是 1。

BigDecimal a = new BigDecimal("1.23")
BigDecimal b = new BigDecimal("3.45")
if (a.compareTo(b) > 0)) { }
Run Code Online (Sandbox Code Playgroud)

我看到有些人在 grails 中使用这种格式:

 if (a > b) {  }
Run Code Online (Sandbox Code Playgroud)

这是否正常工作?即它会得到正确的小数,还是转换为浮点数或类似的并进行比较?

使用 "==" 与使用 equals() 怎么样?

像这样的结果是什么:

BigDecimal a = new BigDecimal("1.00")
BigDecimal b = new BigDecimal("1")
assert (a==b)
Run Code Online (Sandbox Code Playgroud)

它似乎有效,但我们已经在 J​​ava 中根深蒂固,不做这种事情。

+=呢?例如

a+=b?
Run Code Online (Sandbox Code Playgroud)

这是否与

a = a.add(b)
Run Code Online (Sandbox Code Playgroud)

哪里能找到这种东西?我有两本很棒的书,不幸的是都没有提到 BigDecimal 比较或算术,只提到了转换/声明。

Nat*_*hes 2

Groovy 允许运算符重载。当类型实现某些方法时,您可以在该类型上使用相应的运算符。

对于+实现的方法是plus,而不是add。

对于大于或小于比较,Groovy 会在对象上查找compareTo 方法,并==查找名为equals 的方法。(如果您想像在 Java 中使用一样比较引用==,则必须使用is。)

下面是常见数学运算符以及用于重载它们的方法的表:

Operator     Method
a + b        a.plus(b)
a - b        a.minus(b)
a * b        a.multiply(b)
a / b        a.divide(b)
a++ or ++a   a.next()
a-- or --a   a.previous()
a << b       a.leftShift(b)
Run Code Online (Sandbox Code Playgroud)

您可以看到 BigDecimal 重载了其中一些方法(您可以重载加、减、乘和除运算符,但不能重载 next、previous 或 leftShift):

groovy:000> BigDecimal.methods*.name
===> [equals, hashCode, toString, intValue, longValue, floatValue, doubleValue,
byteValue, shortValue, add, add, subtract, subtract, multiply, multiply, divide,
 divide, divide, divide, divide, divide, remainder, remainder, divideAndRemainde
r, divideAndRemainder, divideToIntegralValue, divideToIntegralValue, abs, abs, m
ax, min, negate, negate, plus, plus, byteValueExact, shortValueExact, intValueEx
act, longValueExact, toBigIntegerExact, toBigInteger, compareTo, precision, scal
e, signum, ulp, unscaledValue, pow, pow, movePointLeft, movePointRight, scaleByP
owerOfTen, setScale, setScale, setScale, stripTrailingZeros, toEngineeringString
, toPlainString, round, compareTo, getClass, notify, notifyAll, wait, wait, wait
, valueOf, valueOf, valueOf]
Run Code Online (Sandbox Code Playgroud)

根据对象实现 equals 和 CompareTo 的方式,您可以得到==><>=、 和。<=

因此,该运算符导致已在 BigDecimal 中声明的方法或由 groovy 添加到 BigDecimal 的方法被调用。它绝对不会对像 float 这样的基元类型进行任何类型的转换,以便能够在基元上使用运算符。

该表取自Andrew Glover 和 Scott Davis 撰写的这篇 Developerworks 文章,其中包含更多详细信息并包括示例代码。