Groovy 数字

Groovy支持不同种类整型和十进制文本,由Java的Number类型支持。

5.1 整型类型

整型类型与Java的是一样的:

  • byte

  • char

  • short

  • int

  • long

  • java.lang.BigInteger

你可以用下面的声明创建这些类型的整数:

// 基本类型byte  b = 1char  c = 2short s = 3int   i = 4long  l = 5// 无限精度BigInteger bi =  6

如果你使用def关键字来定义可选的类型,那么整型数字的类型就是可变的: 它能自行适配到合适的类型,以便能持有那个数字。

对于正数:

def a = 1assert a instanceof Integer// Integer.MAX_VALUEdef b = 2147483647assert b instanceof Integer// Integer.MAX_VALUE + 1def c = 2147483648assert c instanceof Long// Long.MAX_VALUEdef d = 9223372036854775807assert d instanceof Long// Long.MAX_VALUE + 1def e = 9223372036854775808assert e instanceof BigInteger

同样的对于负数:

def na = -1assert na instanceof Integer// Integer.MIN_VALUEdef nb = -2147483648assert nb instanceof Integer// Integer.MIN_VALUE - 1def nc = -2147483649assert nc instanceof Long// Long.MIN_VALUEdef nd = -9223372036854775808assert nd instanceof Long// Long.MIN_VALUE - 1def ne = -9223372036854775809assert ne instanceof BigInteger
可选择的基于非10进制的表示

二进制

在Java6和之前,以及在Groovy中,数字可以用十进制,八进制和十六进制来表示, 而在Java7和Groovy2,你可以使用带有0b前缀的二进制记数法:

int xInt = 0b10101111assert xInt == 175short xShort = 0b11001001assert xShort == 201 as shortbyte xByte = 0b11assert xByte == 3 as bytelong xLong = 0b101101101101assert xLong == 2925lBigInteger xBigInteger = 0b111100100001assert xBigInteger == 3873gint xNegativeInt = -0b10101111assert xNegativeInt == -175

八进制

八进制用0开头,后面跟八进制数字的经典模式来指定的。

int xInt = 077assert xInt == 63short xShort = 011assert xShort == 9 as shortbyte xByte = 032assert xByte == 26 as bytelong xLong = 0246assert xLong == 166lBigInteger xBigInteger = 01111assert xBigInteger == 585gint xNegativeInt = -077assert xNegativeInt == -63

十六进制

十六进制用0x开头,后面跟十六进制数字的经典模式来指定的。

int xInt = 0x77assert xInt == 119short xShort = 0xaaassert xShort == 170 as shortbyte xByte = 0x3aassert xByte == 58 as bytelong xLong = 0xffffassert xLong == 65535lBigInteger xBigInteger = 0xaaaaassert xBigInteger == 43690gDouble xDouble = new Double('0x1.0p0')assert xDouble == 1.0dint xNegativeInt = -0x77assert xNegativeInt == -119

5.2 小数

小数类型与Java的一样:

  • float

  • double

  • java.lang.BigDecimal

你可以用以下声明来创建这些小数类型数字:

// primitive typesfloat  f = 1.234double d = 2.345// infinite precisionBigDecimal bd =  3.456

小数可以使用指数,使用e or E的指数表示符,后跟一个可选的符号,和一个整数表示指数值:

assert 1e3  ==  1_000.0assert 2E4  == 20_000.0assert 3e+1 ==     30.0assert 4E-2 ==      0.04assert 5e-1 ==      0.5

为了方便地进行精确的小数的计算,Groovy选择用java.lang.BigDecimal为小数的类型。 此外,无论是float 和 double都是被支持的, 但需要一个显示的类型声明,类型强制或后缀。 即使BigDecimal的是默认的小数类型,但这样的小数是可被用在以float 或 double作为参数的方法或闭包中的。


小数不能使用二进制,八进制或十六进制表示形式来表示。

5.3 在数字中的下划线

当在输入一个很长的数字是,是很难看清楚这些数字的, 通过容许在数字之间输入下划线来分组,这样可以更容易分清楚这些数字:

long creditCardNumber = 1234_5678_9012_3456L
long socialSecurityNumbers = 999_99_9999L
double monetaryAmount = 12_345_132.12
long hexBytes = 0xFF_EC_DE_5E
long hexWords = 0xFFEC_DE5E
long maxLong = 0x7fff_ffff_ffff_ffffL
long alsoMaxLong = 9_223_372_036_854_775_807L
long bytes = 0b11010010_01101001_10010100_10010010

5.4 Number类型的后缀

我们可以用指定后缀(看下表)的方式强制指定一个数字的类型(包括二进制,八进制和十六进制),而这些后缀是不区分大小写的。

类型后缀

BigInteger

G or g

Long

L or l

Integer

I or i

BigDecimal

G or g

Double

D or d

Float

F or f

例子:

assert 42I == new Integer('42')assert 42i == new Integer('42') // lowercase i more readableassert 123L == new Long("123") // uppercase L more readableassert 2147483648 == new Long('2147483648') // Long type used, value too large for an Integerassert 456G == new BigInteger('456')assert 456g == new BigInteger('456')assert 123.45 == new BigDecimal('123.45') // default BigDecimal type usedassert 1.200065D == new Double('1.200065')assert 1.234F == new Float('1.234')assert 1.23E23D == new Double('1.23E23')assert 0b1111L.class == Long // binaryassert 0xFFi.class == Integer // hexadecimalassert 034G.class == BigInteger // octal

5.5 算术运算

虽然操作符将会在后面详细介绍,但讨论算术运算符的行为和运算结果的类型也是非常重要的。

除了除法和指数这两个二元操作符外(后面将会介绍),

  • byte, char, short 和 int之间的二元运算结果将会是int

  • 涉及到long 与 byte, char, short 和 int 的结果将会是 long

  • 涉及到 BigInteger 和其他整型类型的结果将会是BigInteger

  • float, double 和 BigDecimal 之间二元操作的结果将会是 double

  • 两个BigDecimal之间的二元操作结果将会是BigDecimal

下面的表格总结了这些规则:


bytecharshortintlongBigIntegerfloatdoubleBigDecimal

byte

int

int

int

int

long

BigInteger

double

double

double

char


int

int

int

long

BigInteger

double

double

double

short



int

int

long

BigInteger

double

double

double

int




int

long

BigInteger

double

double

double

long





long

BigInteger

double

double

double

BigInteger






BigInteger

double

double

double

float







double

double

double

double








double

double

BigDecimal









BigDecimal


得益于Groovy的操作符重载,常用的算术运算符一样可以用于BigInteger 和 BigDecimal之间,而不用好像Java那样你必须使用显式方法来操作这些数字。

5.5.1 除法运算符的情况

如果其中一个操作数是float或double的话,除法运算/ (和 /= 执行除法和指定)的结果将会是double,其他的都会是BigDecimal (当操作数是short, char, byte, int, long,BigInteger或BigDecimal之间的任意组合)。

BigDecimal division is performed with the divide() method if the division is exact (ie. yielding a result that can be represented within the bounds of the same precision and scale), or using a MathContext with a precision of the maximum of the two operands’ precision plus an extra precision of 10, and a scale of the maximum of 10 and the maximum of the operands’ scale.


对于像Java中的整数除法,你应该使用intdiv()方法,而Groovy中并没有提供专用的整数除法运算符。

5.5.2 幂运算的情况下

幂运算是用**操作符表示,该操作符带有两个参数:底数和指数。 幂运算的结果过取决与他的操作数和运算的结果(尤其是如果结果可被表示为一个整数)

以下是Groovy的幂运算的规则,以确定结果类型:

  • 如果指数是一个十进制值

    • 如果结果可被表示为一个Integer,则返回一个Integer

    • 否则,如果结果可以表示为一个Long,然后返回一个Long

    • 否则返回一个Double

  • 如果指数为整数

    • 如果底数是一个BigDecimal,则返回一个BigDecimal值的结果

    • 如果底数是一个BigInteger,然后返回一个BigInteger结果值

    • 如果底数是一个整数,而且结果可以放进一个Integer类型的话,就返回Integer,否则返回一个BigInteger

    • 如果底数是一个Long,而且结果可以放进一个Long类型的话,就返回Long,否则返回一个BigInteger

    • 当指数为负,则返回一个Integer,Long或Double,这取决与结果值是否合适那个类型

    • 如果该指数是正数或零

我们可以用一些举例来说明这些规则:

// base and exponent are ints and the result can be represented by an Integer
assert    2    **   3    instanceof Integer    //  8
assert   10    **   9    instanceof Integer    //  1_000_000_000

// the base is a long, so fit the result in a Long
// (although it could have fit in an Integer)
assert    5L   **   2    instanceof Long       //  25

// the result can't be represented as an Integer or Long, so return a BigInteger
assert  100    **  10    instanceof BigInteger //  10e20
assert 1234    ** 123    instanceof BigInteger //  170515806212727042875...

// the base is a BigDecimal and the exponent a negative int
// but the result can be represented as an Integer
assert    0.5  **  -2    instanceof Integer    //  4

// the base is an int, and the exponent a negative float
// but again, the result can be represented as an Integer
assert    1    **  -0.3f instanceof Integer    //  1

// the base is an int, and the exponent a negative int
// but the result will be calculated as a Double
// (both base and exponent are actually converted to doubles)
assert   10    **  -1    instanceof Double     //  0.1

// the base is a BigDecimal, and the exponent is an int, so return a BigDecimal
assert    1.2  **  10    instanceof BigDecimal //  6.1917364224

// the base is a float or double, and the exponent is an int
// but the result can only be represented as a Double value
assert    3.4f **   5    instanceof Double     //  454.35430372146965
assert    5.6d **   2    instanceof Double     //  31.359999999999996

// the exponent is a decimal value
// and the result can only be represented as a Double value
assert    7.8  **   1.9  instanceof Double     //  49.542708423868476
assert    2    **   0.1f instanceof Double     //  1.0717734636432956