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

Sau*_*aur 1 double groovy bigdecimal

我对double使用价值感到有些困惑.

当我使用如下: -

double foo = 20.46455
assert 20 == foo.round()
assert 20.46 == foo.round(2)
Run Code Online (Sandbox Code Playgroud)

它工作正常.但当我使用像:

def foo = 20.46455
assert 20 == foo.round()
Run Code Online (Sandbox Code Playgroud)

它抛出: -

显示java.lang.NullPointerException

def foo = 20.46455
assert 20.46 == foo.round(2)
Run Code Online (Sandbox Code Playgroud)

它抛出: -

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

这意味着默认情况下groovy,值保留BigDecimalBigDecimal.round()期望java.math.MathContext作为输入.

但是我的混乱开始时我正在使用Math.round()哪个除了double作为输入然后为什么下面的语句被传递而groovy保留默认情况下BigDecimal

def foo = 20.46455
assert 20 == Math.round(foo)
Run Code Online (Sandbox Code Playgroud)

为什么我必须使用.toDouble()通过我的测试用例,而foo具有double如下格式的价值?

def foo = 20.46455
assert 20 == foo.toDouble().round()
assert 20.46 == foo.toDouble().round(2)
Run Code Online (Sandbox Code Playgroud)

注意: - 我不想知道如何round使用double值,我只是想知道为什么groovy在每种情况下表现不同?

Jos*_*ozo 7

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

例子:

def foo = 20.46455
println foo.getClass()
Run Code Online (Sandbox Code Playgroud)

输出:

class java.math.BigDecimal

double foo = 20.45645
println foo.getClass()
Run Code Online (Sandbox Code Playgroud)

输出:

class java.lang.Double

def foo = 20.45645d
println foo.getClass()
Run Code Online (Sandbox Code Playgroud)

输出:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

class java.lang.Double

class java.lang.BigDecimal

作为一个经验法则,如果数量是基于浮点(double,float,BigDecimal)将有相互之间的隐式类型转换,并试图转换到非浮点数字(比如当代码将抛出异常intlong).如果数字不是浮点类型(int,long),则可以在非浮点类型和浮点类型之间进行转换,因为浮点数也包括非浮点作为子集(例如,1可以用1.0表示).这是有道理的,因为你不能将浮点信息从float传递给int(20.5不能用int变量表示),但在大多数情况下你可以做相反的事情,偶尔会出现溢出溢出的情况值(例如,变量中的一个非常大的long数字float).