在 groovy/grails 中对 BigDecimal 使用比较运算符安全吗?
is it safe to use comparison operators on BigDecimal in groovy/grails?
比较两个 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) { }
这个工作正常吗? IE。它会得到正确的小数点,还是会转换为浮点数或类似值并进行比较?
使用“==”与使用 equals() 相比如何?
这样的结果是什么:
BigDecimal a = new BigDecimal("1.00")
BigDecimal b = new BigDecimal("1")
assert (a==b)
这似乎有效,但我们已经根深蒂固 Java 不要做这种事情。
+=怎么样?例如
a+=b?
这会和
一样吗
a = a.add(b)
这种东西哪里找的?我有两本 groovy 书,不幸的是,它们都没有提到 BigDecimal 比较或算术,只有 conversion/declaration.
Groovy 允许运算符重载。当一个类型实现某些方法时,您可以在该类型上使用相应的运算符。
对于+
实现的方法是plus,不是add。
对于大于或小于比较,Groovy 在对象上查找 compareTo 方法,对于 ==
它查找名为 equals 的方法。 (如果你想比较引用,就像在 Java 中使用 ==
,你必须使用 is
。)
下面是 table 常用数学运算符以及用于重载它们的方法:
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 这样的基元类型进行任何类型的转换。
table 取自 this developerworks article by Andrew Glover and Scott Davis,其中包含更多详细信息和示例代码。
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 中了解所有这些内容,并提供全面的示例。
简短的回答是 是 ,在 Groovy 中使用 ==
进行 BigDecimal
比较是安全的。
来自 Groovy 文档 Behaviour of == 部分:
In Java ==
means equality of primitive types or identity for objects. In Groovy ==
translates to a.compareTo(b)==0
, if they are Comparable
, and a.equals(b)
otherwise. To check for identity, there is is
. E.g. a.is(b)
.
比较两个 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) { }
这个工作正常吗? IE。它会得到正确的小数点,还是会转换为浮点数或类似值并进行比较?
使用“==”与使用 equals() 相比如何?
这样的结果是什么:
BigDecimal a = new BigDecimal("1.00")
BigDecimal b = new BigDecimal("1")
assert (a==b)
这似乎有效,但我们已经根深蒂固 Java 不要做这种事情。
+=怎么样?例如
a+=b?
这会和
一样吗a = a.add(b)
这种东西哪里找的?我有两本 groovy 书,不幸的是,它们都没有提到 BigDecimal 比较或算术,只有 conversion/declaration.
Groovy 允许运算符重载。当一个类型实现某些方法时,您可以在该类型上使用相应的运算符。
对于+
实现的方法是plus,不是add。
对于大于或小于比较,Groovy 在对象上查找 compareTo 方法,对于 ==
它查找名为 equals 的方法。 (如果你想比较引用,就像在 Java 中使用 ==
,你必须使用 is
。)
下面是 table 常用数学运算符以及用于重载它们的方法:
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 这样的基元类型进行任何类型的转换。
table 取自 this developerworks article by Andrew Glover and Scott Davis,其中包含更多详细信息和示例代码。
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 中了解所有这些内容,并提供全面的示例。
简短的回答是 是 ,在 Groovy 中使用 ==
进行 BigDecimal
比较是安全的。
来自 Groovy 文档 Behaviour of == 部分:
In Java
==
means equality of primitive types or identity for objects. In Groovy==
translates toa.compareTo(b)==0
, if they areComparable
, anda.equals(b)
otherwise. To check for identity, there isis
. E.g.a.is(b)
.