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

问题描述 投票:4回答:3

比较两个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比较或算术,也没有提到转换/声明。

groovy comparison operator-keyword bigdecimal
3个回答
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
投票

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中的所有这些。


0
投票

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

从Groovy文档Behaviour of ==部分:

在Java中,==表示基本类型的平等或对象的标识。在Groovy ==翻译为a.compareTo(b)==0,如果他们是Comparable,和a.equals(b)否则。要检查身份,有is。例如。 a.is(b)

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