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

时间:2015-05-07 12:16:13

标签: groovy comparison operator-keyword bigdecimal

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

BigDecimal a = new BigDecimal("1.23")
BigDecimal b = new BigDecimal("3.45")
if (a.compareTo(b) > 0)) { }

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

 if (a > b) {  }

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

如何使用“==”vs使用equals()?

这样的结果是什么:

BigDecimal a = new BigDecimal("1.00")
BigDecimal b = new BigDecimal("1")
assert (a==b)

它似乎有效,但我们已经用Java编写了这样的东西而不是做这种事情。

怎么样+ =?例如

a+=b?

这与

相同吗?
a = a.add(b)

人们在哪里找到这种东西?我有两本时髦的书,不幸的是既没有提到BigDecimal比较或算术,也没有提到转换/声明。

3 个答案:

答案 0 :(得分:2)

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

对于+,要实现的方法是加号,而不是添加。

对于大于或小于比较,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)

你可以看到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]

根据您的对象实现equals和compareTo的方式,您得到==><>=<=

因此,运算符导致已经在BigDecimal中声明的方法,或者通过groovy添加到BigDecimal,以进行调用。它绝对不会像float这样转换为原始类型,以便能够在原语上使用运算符。

该表取自this developerworks article by Andrew Glover and Scott Davis,其中包含更多详细信息并包含示例代码。

答案 1 :(得分:1)

Groovy在管理数字和无限精确方面做得非常出色。首先你应该知道的是,任何带有点的数字默认为BigDecimal--无限精度的原因。以下是这意味着什么的一个例子。请考虑以下代码段:

    System.out.println(2.0 - 1.1);
    System.out.println(new BigDecimal(2.0).subtract(new BigDecimal(1.1)));
    System.out.println(new BigDecimal("2.0").subtract(new BigDecimal("1.1")));

    // the above will give these:
    0.8999999999999999
    0.899999999999999911182158029987476766109466552734375
    0.9

这显示了我们在Java中获得体面的耐力。在Groovy中,您需要做的就是:

println 2 - 1.1​

获得0.9!在Groovy web console上试试这个。这里,第二个操作数是一个BigDecimal,所以整个计算都在BigDecimal中,而精度是Groovy在这种情况下努力完成清理的目的。

但是怎么样?这是因为几乎Groovy中的每个操作符都映射到引擎盖下的对象上的方法调用,因此 a + b a.plus(b),而 a == b 转换为 a.compareTo(b)。因此,可以安全地假设您所假设的内容,这是Groovy的处理方式:少写,表达,Groovy将为您完成工作。您可以在Groovy-lang documentation page中了解所有这些,并附上示例。

答案 2 :(得分:0)

简短的回答是,在Groovy中使用==进行BigDecimal比较是安全的。

来自Groovy文档Behaviour of ==部分:

  

在Java中,==表示对象的原始类型或身份相同。在Groovy中,==转换为a.compareTo(b)==0,如果它们是Comparable,则转换为a.equals(b)。要检查身份,有is。例如。 a.is(b)