当 groovy 决定在 double 与 BigDecimal 中创造价值时,使用 double 值会造成混淆吗?
Confusion using with double value, when groovy decides to make value in double vs BigDecimal?
我对使用 double
值有点困惑。
当我如下使用时:-
double foo = 20.46455
assert 20 == foo.round()
assert 20.46 == foo.round(2)
一切正常。但是当我使用像 as :-
这样的东西时
def foo = 20.46455
assert 20 == foo.round()
它抛出:-
java.lang.NullPointerException
和
def foo = 20.46455
assert 20.46 == foo.round(2)
它抛出:-
groovy.lang.MissingMethodException: No signature of method: java.math.BigDecimal.round() is applicable for argument types: (java.lang.Integer) values: [2]
Possible solutions: round(java.math.MathContext), find(), pow(int), power(java.lang.Integer), find(groovy.lang.Closure), and(java.lang.Number)
这意味着在 groovy
中默认,在 BigDecimal
和 BigDecimal.round()
中保留值期望 java.math.MathContext
作为输入。
但是当我使用 Math.round()
时我开始感到困惑,除了 double
作为输入然后 为什么下面的语句被传递而 groovy 默认保留在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
一个双精度值,我只想知道为什么 groovy
在每个案例??
Groovy 自动隐式地对任何浮点数使用 BigDecimal,除非您定义类型或为数字添加后缀(如 D)。
示例:
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()
只接受 double
和 float
原语作为参数,代码却不接受的原因通过 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
根据经验,如果数字是基于浮点数的(double
、float
、BigDecimal
),彼此之间将进行隐式类型转换,并且尝试转换为非浮点数(如 int
或 long
)时,代码将抛出异常。如果数字不是浮点类型(int
,long
),它可以在非浮点类型和浮点类型之间转换,因为浮点数也包括非浮点数作为子集(例如 1 可以用 1.0 表示)。这是有道理的,因为你不能将浮点信息从 float 传递到 int(20.5 不能用 int
变量表示),但在大多数情况下你可以做相反的事情,偶尔大值的溢出异常(例如,一个非常大的 long
数字进入 float
变量)。
我对使用 double
值有点困惑。
当我如下使用时:-
double foo = 20.46455
assert 20 == foo.round()
assert 20.46 == foo.round(2)
一切正常。但是当我使用像 as :-
这样的东西时def foo = 20.46455
assert 20 == foo.round()
它抛出:-
java.lang.NullPointerException
和
def foo = 20.46455
assert 20.46 == foo.round(2)
它抛出:-
groovy.lang.MissingMethodException: No signature of method: java.math.BigDecimal.round() is applicable for argument types: (java.lang.Integer) values: [2] Possible solutions: round(java.math.MathContext), find(), pow(int), power(java.lang.Integer), find(groovy.lang.Closure), and(java.lang.Number)
这意味着在 groovy
中默认,在 BigDecimal
和 BigDecimal.round()
中保留值期望 java.math.MathContext
作为输入。
但是当我使用 Math.round()
时我开始感到困惑,除了 double
作为输入然后 为什么下面的语句被传递而 groovy 默认保留在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
一个双精度值,我只想知道为什么 groovy
在每个案例??
Groovy 自动隐式地对任何浮点数使用 BigDecimal,除非您定义类型或为数字添加后缀(如 D)。
示例:
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()
只接受 double
和 float
原语作为参数,代码却不接受的原因通过 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
根据经验,如果数字是基于浮点数的(double
、float
、BigDecimal
),彼此之间将进行隐式类型转换,并且尝试转换为非浮点数(如 int
或 long
)时,代码将抛出异常。如果数字不是浮点类型(int
,long
),它可以在非浮点类型和浮点类型之间转换,因为浮点数也包括非浮点数作为子集(例如 1 可以用 1.0 表示)。这是有道理的,因为你不能将浮点信息从 float 传递到 int(20.5 不能用 int
变量表示),但在大多数情况下你可以做相反的事情,偶尔大值的溢出异常(例如,一个非常大的 long
数字进入 float
变量)。