混淆使用double值,当groovy决定使用double和BigDecimal的值时?

时间:2016-09-09 11:13:20

标签: groovy double bigdecimal

使用double值时,我有点困惑。

当我使用如下: -

double foo = 20.46455
assert 20 == foo.round()
assert 20.46 == foo.round(2)

工作正常。但是当我使用像: -

这样的东西时
def foo = 20.46455
assert 20 == foo.round()
抛出: -

  

显示java.lang.NullPointerException

def foo = 20.46455
assert 20.46 == foo.round(2)
抛出: -

  

groovy.lang.MissingMethodException:没有方法签名:java.math.BigDecimal.round()适用于参数类型:(java.lang.Integer)值:[2]   可能的解决方案:round(java.math.MathContext),find(),pow(int),power(java.lang.Integer),find(groovy.lang.Closure)和(java.lang.Number)

默认情况下,这意味着groovyBigDecimal中的值保留,BigDecimal.round()期望java.math.MathContext作为输入。

但是,当我使用除double之外的Math.round()作为输入时,我的混淆就开始了,然后为什么在BigDecimal

def foo = 20.46455
assert 20 == Math.round(foo)

为什么我必须使用.toDouble()来传递我的测试用例,foo具有double格式的值,如下所示?

def foo = 20.46455
assert 20 == foo.toDouble().round()
assert 20.46 == foo.toDouble().round(2)

注意: - 我不想知道如何round一个double值,我只是想知道为什么groovy在每种情况下表现不同?< / p>

1 个答案:

答案 0 :(得分:6)

除非您定义类型或为数字添加后缀(如D),否则Groovy会自动并隐式地将BigDecimal用于任何浮点数。

<强>示例:

def foo = 20.46455
println foo.getClass()

输出

  

class java.math.BigDecimal

double foo = 20.45645
println foo.getClass()

输出

  

class java.lang.Double

def foo = 20.45645d
println foo.getClass()

输出

  

class java.lang.Double

输入转化次数

Groovy也有一些自动类型转换,这就是为什么Math.round()只接受doublefloat原语作为参数的原因,当你传递BigDecimal时代码没有失败。为了证明这一点,您可以实现自己的round函数并检查类型转换会发生什么:

<强>示例:

def round(double foo) {
   println foo.getClass()
   return foo.round()
}

def foo = 20.46455
println foo.getClass()
assert 20 == round(foo)

<强>输出:

  

class java.math.BigDecimal

     

class java.lang.Double

隐式转换的一些更有效的例子:

def round(float foo) {
   println foo.getClass()
   return foo.round()
}

def foo = 20.46455
println foo.getClass()
assert 20 == round(foo)

<强>输出:

  

class java.math.BigDecimal

     

class java.lang.Float

def round(float foo) {
   println foo.getClass()
   return foo.round()
}

def foo = 20
println foo.getClass()
assert 20 == round(foo)

<强>输出:

  

class java.lang.Integer

     

class java.lang.Float

def round(double foo) {
   println foo.getClass()
   return foo.round()
}

def foo = 20
println foo.getClass()
assert 20 == round(foo)

<强>输出:

  

class java.lang.Integer

     

class java.lang.Double

def round(BigDecimal foo) {   
   println foo.getClass()
   return foo
}

double foo = 20.0
println foo.getClass()
assert 20 == round(foo)

输出:

  

class java.lang.Double

     

class java.lang.BigDecimal

根据经验,如果数字是基于浮点的(doublefloatBigDecimal),则彼此之间将存在隐式类型转换,代码将尝试转换为非浮点数时抛出异常(例如intlong)。如果数字不是浮点类型(intlong),则可以在非浮点类型和浮点类型之间进行转换,因为浮点数也包括非浮点类型作为子集(例如,1可以用1.0表示。这是有道理的,因为你不能将浮点信息从float传递给int(20.5不能用int变量表示),但在大多数情况下你可以做相反的事情,偶尔大值溢出的例外(例如,long变量中的float数字非常大。)