Groovy numbers are either decimals or integers. The 3 main types of integers are Integer, Long, and BigInteger. BigInteger has no size limit, while Integer and Long do. We can enquire their minimum and maximum values:
assert Integer.MAX_VALUE == 2147483647 assert Integer.MIN_VALUE == -2147483648
assert Long.MAX_VALUE == 9223372036854775807
assert Long.MIN_VALUE == -9223372036854775808
Integers will normally be the smallest type into which the value will fit (using 2's-complement representation):
assert 110.class == Integer
assert 3000000000.class == Long assert 10000000000000000000.class == BigInteger
We can represent integers in base-10, hexadecimal, or octal notation:
[ 2, -17, +987 ].each{ assert it }
[ 0xACe, 0X01ff ].each{ assert it }
[ 077, 01 ].each{ assert it }
We can negate hexadecimals and octals to represent negative numbers.
assert 0x7FFFFFFF.class == Integer
assert (-0x7FFFFFFF).class == Integer assert 0x80000000.class == Long
assert (-0x80000000).class == Integer
assert (-0x80000001).class == Long
We can force an integer (including hexadecimals and octals) to have a specific type by giving a suffix (I for Integer, L for Long, G for BigInteger), either uppercase or lowercase:
assert 42i.class == Integer assert 123L.class == Long assert 456g.class == BigInteger
assert 0xFFi.class == Integer
Fixed-Size Integers
The fixed-size integers, Integer and Long, each have size limits but are more efficient in calculations.
There are also the less common Byte and Short types of integer, which act like the Integer type in math operations.
assert Short.MAX_VALUE == 32767
assert Short.MIN_VALUE == -32768
assert Byte.MAX_VALUE == 127
assert Byte.MIN_VALUE == -128
def a= new Byte('34'), b= new Byte('2')
assert (a+b).class == Integer
We can enquire the bit-size of each type of fixed-size integer:
assert Integer.SIZE == 32
assert Long.SIZE == 64
assert Short.SIZE == 16
assert Byte.SIZE == 8
The class Integer can often be written int. The classes Long, Short, and Byte can each also often be written uncapitalized, ie, long, short, and byte. We can enquire these alternative (aka "primitive type") names:
assert Integer.TYPE == int
assert Long.TYPE == long
assert Short.TYPE == short
assert Byte.TYPE == byte
The fixed-size integer classes can be converted to one another:
assert 45L as Integer == 45i
assert 45L as int == 45i assert 45L.toInteger() == 45i assert 23L.intValue() == 23i
assert 45i as Long == 45L
assert 45i as long == 45L
assert 23i.toLong() == 23L
assert 45i.longValue() == 45L
assert 256i as Byte == 0
assert 200i as byte == -56
We can create new fixed-sized integers from strings:
assert '42'.toInteger() == 42i
assert '56'.toLong() == 56L
try{ 'moo'.toLong(); assert false }
catch(e){ assert e instanceof NumberFormatException }
assert new Integer( '45' ) == 45i
assert new Byte( '45' ) == 45 as byte
try{ new Integer( 'oink' ); assert false }
catch(e){ assert e instanceof NumberFormatException }
To convert from a fixed-size integer to a string in various bases:
assert Integer.toString( 29, 16 ) == '1d'
assert Long.toString( 29L, 16 ) == '1d'
assert Integer.toString( -29, 16 ) == '-1d'
assert Integer.toString(0) == '0'
assert Integer.toString( 29, 16 ).toUpperCase() == '1D'
assert Integer.toString( 29 ) == '29'
assert Short.toString( 29 as short ) == '29'
If the base/radix isn't between Character.MIN_RADIX and Character.MAX_RADIX, base 10 is used instead:
assert Integer.toString( 999, Character.MIN_RADIX - 1 ) ==
Integer.toString( 999, 10 )
assert Integer.toString( 999, Character.MAX_RADIX + 1 ) ==
Integer.toString( 999, 10 )
assert Character.MAX_RADIX == 36
The common bases have similar methods which always return an unsigned integer:
assert Integer.toHexString(29) == '1d' assert Integer.toHexString(0) == '0'
assert Integer.toHexString(-17) == 'ffffffef'
assert Long.toHexString(-17L) == 'ffffffffffffffef'
assert Integer.toHexString(29) == Integer.toString(29,16)
assert Integer.toHexString(-17) != Integer.toString(-17,16)
assert Integer.toOctalString(29) == '35'
assert Integer.toOctalString(0) == '0'
assert Integer.toOctalString(-17) == '37777777757'
assert Integer.toBinaryString(29) == '11101'
We can convert a string representation to an integer, using a specified base/radix:
assert Integer.parseInt("0", 10) == 0
assert Integer.parseInt("473", 10) == 473
assert Long.parseLong("473", 10) == 473L assert Integer.parseInt("473") == 473 assert Integer.parseInt("-0", 10) == 0
assert Integer.parseInt("-FF", 16) == -255
assert Integer.parseInt("1100110", 2) == 102
assert Integer.parseInt("2147483647", 10) == 2147483647
assert Integer.parseInt("-2147483648", 10) == -2147483648
assert Integer.parseInt("Kona", 27) == 411787
assert Long.parseLong("Hazelnut", 36) == 1356099454469L
assert Short.parseShort("-FF", 16) == -255
A NumberFormatException may be thrown:
[ { Integer.parseInt("2147483648", 10) }, { Integer.parseInt("99", 8) }, { Integer.parseInt("Kona", 10) }, { Integer.parseInt("1111", Character.MIN_RADIX - 1 ) }, { Integer.parseInt("1111", Character.MAX_RADIX + 1 ) }, { Integer.parseInt( '@#$%' ) }, { Integer.parseInt( '' ) }, ].each{ c->
try{ c(); assert false }
catch(e){assert e instanceof NumberFormatException}
}
An alternative method name is:
assert Integer.valueOf( '12af', 16 ) == 0x12af
assert Long.valueOf( '123' ) == 123
assert Short.valueOf( 027 as short ) == 027
We can convert a string to a fixed-size integer, similar to parseInt() etc, but with the radix instead indicated inside the string:
assert Integer.decode('0xff') == 0xFF
assert Integer.decode('#FF') == 0xFF
assert Long.decode('#FF') == 0xFFL assert Short.decode('#FF') == 0xFF as short
assert Byte.decode('#F') == 0xF as byte
assert Integer.decode('-077') == -077
assert Integer.decode('2345') == 2345
try{ Integer.decode('7 @8'); assert false }
catch(e){ assert e instanceof NumberFormatException }
We can return an integer representing the sign:
assert Integer.signum(45i) == 1
assert Integer.signum(0i) == 0
assert Integer.signum(-43i) == -1
assert Long.signum(-43L) == -1
We can compare fixed-size integers with each other:
assert 45i.compareTo( 47L ) < 0
assert (45 as byte).compareTo( 43 as short ) > 0
assert 45.compareTo( 45 ) == 0
Calculations with Fixed-Size Integers
We can perform addition, subtraction, multiplication, exponents, modulos, and negations on Integers and Longs, using both an operator syntax and a method syntax:
assert 34 + 33 == 67 && 34.plus( 33 ) == 67
assert 34L - 21L == 13L && 34L.minus( 21L ) == 13L
assert 3 * 31 == 93 && 3.multiply( 31 ) == 93
assert 23 % 3 == 2 && 23.mod( 3 ) == 2
assert 3**2 == 9 && 3.power( 2 ) == 9
Not all calculations have a special operator symbol:
assert 22.intdiv(5) == 4
assert (-22).intdiv(5) == -4
assert (-34).abs() == 34
assert (-34L).abs() == 34L
We can increment and decrement variables, using operators, either before and after evaluation:
def a= 7
assert a++ == 7 && a == 8 && a-- == 8 && a == 7 &&
++a == 8 && a == 8 && --a == 7 && a == 7
def b = 7, c = 7 assert ( ++b ) == ( c = c.next() )
assert b == c
assert ( --b ) == ( c = c.previous() )
assert b == c
assert ( b++ ) == { def z = c; c = c.next(); z }()
assert b == c
def b= Integer.MAX_VALUE
assert ++b == Integer.MIN_VALUE && --b == Integer.MAX_VALUE
Rules of parentheses and precedence apply to these operators. The operators have the same precedence irrespective of what type of values they operate on.
assert 3*(4+5) != 3*4+5
assert -3**2 == -(3**2) assert ( 2*3**2 == 2*(3**2) ) && ( 2*3**2 != (2*3)**2 )
assert -3+2 != -(3+2) assert -~234 == -(~234)
assert 3*4%5 == (3*4)%5 assert 3%4*5 == (3%4)*5
assert 4+5-6 == 3
assert 5+3*4 == 5+(3*4)
Integers often convert their types during math operations. For + - *, a Long with an Integer converts the Integer to a Long:
assert (23i+45L).class == Long
Because the fixed-sized integers have fixed width, they might overflow their boundaries during math operations, so we need to be aware of the range of values we'll use a fixed-size integer for:
assert 256*256*256*256 == 0
assert 256L*256*256*256 == 4294967296L
We can compare fixed-size integers using < <= > >= operators, of lower precedence than addition/etc:
assert 14 > 7 && 14.compareTo(7) > 0
assert 14 >= 8 && 14.compareTo(8) >= 0
assert -4 < 3 && (-4).compareTo(3) < 0
assert -14 <= -9 && (-14).compareTo(-9) <= 0
The operators == != <=> are of lower precedence than the other comparison operators:
def a = 4, b = 4, c = 5
assert a == b && a.equals(b)
assert a != c && ! a.equals(c)
assert (4 <=> 7) == -1 && 4.compareTo(7) == -1
assert (4 <=> 4) == 0 && 4.compareTo(4) == 0
assert (4 <=> 2) == 1 && 4.compareTo(2) == 1
Bit-Manipulation on Fixed-Sized Integers
We can examine and manipulate the individual bits on the fixed-sized integers.
To return an int or long with a single 1-bit in the position of the highest-order 1-bit in the argument:
assert Integer.highestOneBit( 45 ) == 32
assert Integer.highestOneBit( 27 ) == 16
assert Integer.highestOneBit( 0 ) == 0
assert Integer.highestOneBit( -1 ) == -128*256*256*256
assert Long.highestOneBit( -1L ) == -128*256*256*256 * 256*256*256*256
assert Integer.lowestOneBit( 45i ) == 1 assert Integer.lowestOneBit( 46i ) == 2
assert Integer.lowestOneBit( 48i ) == 16
To return the number of zero bits preceding the highest-order 1-bit:
[ 0:32, 1:31, 2:30, 4:29 ].each{ k, v->
assert Integer.numberOfLeadingZeros( k ) == v
assert Long.numberOfLeadingZeros( k as long ) == v + 32
}
[ 0:32, 45:0, 46:1, 48:4 ].each{ k, v->
assert Integer.numberOfTrailingZeros( k ) == v
}
assert Integer.bitCount( 7 ) == 3
assert Integer.bitCount( -1 ) == 32
We can perform a bitwise complement of the bits in a fixed-size integer using the ~ operator:
def x= 0x33333333i
assert ~x == -x - 1
We can shift the bits of a fixed-size integer to the left or right. This is of lower precedence than addition/etc, but higher than the comparison operators.
assert 0xB4F<<4 == 0xB4F0 && 0xB4F.leftShift( 4 ) == 0xB4F0
assert 0xD23C>>4 == 0xD23 && 0xD23C.rightShift( 4 ) == 0xD23
assert -0xFFF>>4 == -0x100 && (-0xFFF).rightShift( 4 ) == -0x100
assert -0xFFF>>>4 == 0xFFFFF00 && (-0xFFF).rightShiftUnsigned(4) == 0xFFFFF00
[ 0xABC, -0x98765 ].each{
it << 8 == it >> -8
}
We can rotate the bits in an integer or long:
assert Integer.rotateLeft( 0x456789AB, 4 ) == 0x56789AB4
assert Integer.rotateLeft( 0x456789AB, 12 ) ==
Integer.rotateRight( 0x456789AB, Integer.SIZE - 12 )
assert Integer.rotateLeft( 0x456789AB, 32 ) == 0x456789AB
assert Long.rotateRight( 0x0123456789ABCDEF, 40 ) == 0x6789ABCDEF012345
We can perform bitwise 'and', 'or', and 'xor' operations on fixed-size integers. This is of lower precedence than the comparison operators.
assert (0x33 & 0x11) == 0x11 && 0x33.and(0x11) == 0x11
assert (0x33 | 0x11) == 0x33 && 0x33.or(0x11) == 0x33
assert (0x33 ^ 0x11) == 0x22 && 0x33.xor(0x11) == 0x22
We can reverse the bits or bytes of the binary representation of an int or long:
assert Integer.toString( 123456, 2 ) == '11110001001000000'
assert Integer.toString( Integer.reverse( 123456 ), 2 ) ==
'10010001111000000000000000'
assert Integer.reverseBytes( 0x157ACE42 ) == 0x42CE7A15
Boolean, Conditional, and Assignment Operators with Fixed-Sized Integers
The boolean, conditional, and assignment operators are of even lower precedence than the bitwise operators.
When using an integer with boolean operators !, &&, and ||, 0 evaluates to false, while every other integer evaluates to true:
assert ! 0; assert 1; assert 2; assert -1; assert -2
assert ( ! 1 && 0 ) != ( ! (1 && 0) )
assert ( 1 || 0 && 0 ) != ( (1 || 0) && 0 )
The boolean operators && and || only have their operands evaluated until the final result is known. This affects operands with side effects, such as increment or decrement operators:
def x = 0
0 && x++
assert x == 0
1 || x++
assert x == 0
We can use the conditional operator ?:, of lower precedence than the boolean operators, to choose between two values:
def x= 1? 7: -5
assert x == 7
We can put the assignment operator = within expressions, but must surround it with parentheses because its precedence is lower than the conditional:
def x, y = (x = 3) && 1
assert (x == 3) && y
def i = 2, j = (i=3) * i
assert j == 9
Of equal precedence as the plain assignment operator = are the quick assignment *= += -= %= **= <<= >>= >>>= &= ^= |= operators:
def a = 7
a += 2 assert a == 9
a += (a = 3) assert a == 12
BigIntegers
The BigInteger has arbitrary precision, growing as large as necessary to accommodate the results of an operation.
We can explicitly convert fixed-sized integers to a BigInteger, and vice versa:
assert 45i as BigInteger == 45g
assert 45L.toBigInteger() == 45g
assert 45g as Integer == 45i
assert 45g.intValue() == 45i assert 45g as Long == 45L
assert 45g.longValue() == 45L
assert 256g as Byte == 0
assert 200g as byte == -56
A method and some fields that give a little more efficiency:
assert BigInteger.valueOf( 45L ) == 45g
assert BigInteger.ZERO == 0g
assert BigInteger.ONE == 1g
assert BigInteger.TEN == 10g
We can construct a BigInteger using an array of bytes:
assert new BigInteger( [1,2,3] as byte[] ) == 1g*256*256 + 2*256 + 3
try{new BigInteger( [] as byte[] ); assert 0}
catch(e){assert e instanceof NumberFormatException}
assert new BigInteger( -1, [1,2] as byte[] ) == -258g
assert new BigInteger( 1, [1,2] as byte[] ) == 258g
assert new BigInteger( 0, [0,0] as byte[] ) == 0g
assert new BigInteger( 1, [] as byte[] ) == 0
try{ new BigInteger( 2, [1,2,3] as byte[] ); assert 0 }
catch(e){ assert e instanceof NumberFormatException}
We can convert a BigInteger back to an array of bytes:
def ba= (1g*256*256 + 2*256 + 3).toByteArray()
assert ba.size() == 3 && ba[ 0 ] == 1 && ba[ 1 ] == 2 && ba[ 2 ] == 3
def bb= 255g.toByteArray()
assert bb.size() == 2 && bb[ 0 ] == 0 && bb[ 1 ] == -1
def bc= (-(2g*256 + 3)).toByteArray()
assert bc.size() == 2 && bc[ 0 ] == -3 && bc[ 1 ] == -3
We can pass in a string in a certain base/radix:
assert '27'.toBigInteger() == 27g
assert new BigInteger("27", 10) == 27g
assert new BigInteger("27") == 27g assert new BigInteger("110", 2) == 6g
assert new BigInteger("-1F", 16) == -31g
[ { new BigInteger(" 27", 10) }, { new BigInteger("Z", Character.MAX_RADIX + 1 ) }, { new BigInteger("0", Character.MIN_RADIX - 1 ) }, ].each{
try{ it(); assert 0 }catch(e){ assert e instanceof NumberFormatException }
}
We can convert the BigInteger back to a string:
assert 6g.toString(2) == '110'
assert (-31g).toString(16) == '-1f'
assert 27g.toString() == '27' assert 27g.toString( Character.MAX_RADIX + 1 ) == '27'
We can construct a randomly-generated BigInteger:
assert new BigInteger( 20, new Random() ).toString( 2 ).size() == 20
assert new BigInteger( 20, new Random() ) >= 0
Arithmetic with BigIntegers
We can perform the usual arithmetic operations + - * using either methods or operations:
assert 34g.plus( 33g ) == 34g + 33g
assert 34g.add( 33g ) == 34g + 33g assert 34g.minus( 21g ) == 34g - 21g
assert 34g.subtract( 21g ) == 34g - 21g assert 3g.multiply( 31g ) == 3g * 31g
assert 7g.negate() == -7g assert (-7g).negate() == 7g
For + - *, a BigInteger causes any fixed-width integers in the calculation to be converted to a BigInteger:
assert (45L + 123g).class == BigInteger
assert (23 - 123g).class == BigInteger
assert ( 3g * 31 ).class == BigInteger
assert ( 3 * 31g ).class == BigInteger
assert 3g.multiply( 31 ).class == BigInteger
assert 3.multiply( 31g ).class == BigInteger
We can introduce a BigInteger into an expression with Integers or Longs if overflow may occur. But make sure the BigInteger is introduced before an intermediate value that may overflow, for example, the first-used value in a calculation:
assert 256L*256*256*256 * 256*256*256*256 == 0
assert 256g*256*256*256 * 256*256*256*256 == 18446744073709551616
We can also increment and decrement BigIntegers:
def a= 7g
assert a++ == 7g && a == 8g && a-- == 8g && a == 7g &&
++a == 8g && a == 8g && --a == 7g && a == 7g
We can find out the quotient and remainder:
assert 7g.divide( 4g ) == 1g
assert 7g.remainder( 4g ) == 3g
def a= 7g.divideAndRemainder( 4g )
assert a[0] == 1g assert a[1] == 3g
assert 7g.divide( -4g ) == -1g
assert 7g.remainder( -4g ) == 3g
assert (-7g).divide( 4g ) == -1g
assert (-7g).remainder( 4g ) == -3g
assert (-7g).divide( -4g ) == 1g
assert (-7g).remainder( -4g ) == -3g
Other methods for arithmetic:
assert 22g.intdiv(5g) == 4g
assert (-22g).intdiv(5g) == -4g
assert 7g.abs() == 7g assert (-7g).abs() == 7g
assert 28g.gcd(35g) == 7g
assert (-28g).gcd(35g) == 7g
assert 28g.gcd(-35g) == 7g
assert (-28g).gcd(-35g) == 7g
assert 0g.gcd(9g) == 9g
assert 0g.gcd(0g) == 0g
assert 4g**3 == 64g assert (4g**3).class == Integer
assert 4g.power(3) == 64g assert 4g.pow(3) == 64g
assert (-4g).power(3) == -64g
assert 4g.power(0) == 1g
assert 7g % 4g == 3g && 7g.mod( 4g ) == 3g
assert 8g % 4g == 0g
assert -7g % 4g == 1g
try{ 7g % -4g; assert 0 }catch(e){ assert e instanceof ArithmeticException }
assert 4g.modPow( 3g, 9g ) == 1
assert 4g.modPow( -2g, 9g ) == 4
assert 4g.modInverse( 3g ) == 1
assert 7g.max(5g) == 7g assert 4g.min(5g) == 4g
def a=5g, b=5g, c=a.min(b)
assert [a,b].any{ c.is(it) }
assert (-45g <=> -43g) && ( (-45g).compareTo( -43g ) == -1 )
assert 14g >= 8g && 14g.compareTo(8g) >= 0
assert 45g.signum() == 1 assert 0g.signum() == 0
assert (-43g).signum() == -1
We can construct a randomly generated positive BigInteger with a specified bit length (at least 2 bits), that is probably prime to a specific certainty. The probability the BigInteger is prime is >(1 - (1/2)**certainty). If the certainty <=0, true always returned. The execution time is proportional to the value of this parameter. We must pass in a new Random object:
100.times{
def primes= [17g, 19g, 23g, 29g, 31g]
assert new BigInteger( 5, 50, new Random() ) in primes
}
def pp= BigInteger.probablePrime( 20, new Random() )
def pn= pp.nextProbablePrime()
( (pp+1)..<pn ).each{
assert ! it.isProbablePrime(50)
}
assert 10g.nextProbablePrime() == 11
assert 0g.nextProbablePrime() == 2
Bit-Manipulation on BigIntegers
All operations behave as if BigIntegers were represented in two's-complement notation.
Bit operations operate on a single bit of the two's-complement representation of their operand/s. The infinite word size ensures that there are infinitely many virtual sign bits preceding each BigInteger. None of the single-bit operations can produce a BigInteger with a different sign from the BigInteger being operated on, as they affect only a single bit.
assert 0x33g.testBit(1)
assert ! 0x33g.testBit(2)
(2..100).each{
assert (-0x3g).testBit(it)
}
Unlike with fixed-width integers, BigIntegers don't have a method to show the hex, octal, or binary representation of a negative number. We can use this code instead to look at the first 16 lowest-order virtual bits:
def binRepr={n->
(15..0).inject(''){flo,it->
flo<< (n.testBit(it)? 1: 0)
}
}
assert 0x33g.toString(2) == '110011'
assert binRepr(0x33g) as String == '0000000000110011'
assert (-0x33g).toString(2) == '-110011' assert binRepr(-0x33g) as String == '1111111111001101'
More bit-manip methods:
assert 0x33g.setBit(6) == 0x73g assert 0x33g.clearBit(4) == 0x23g
assert 0x33g.flipBit(1) == 0x31g
assert 0x33g.flipBit(2) == 0x37g
assert 0x1g.getLowestSetBit() == 0
assert 0x2g.getLowestSetBit() == 1
assert 0x8g.getLowestSetBit() == 3
assert 0x33g.bitLength() == 6
assert (-0x33g).bitLength() == 6 assert 0x33g.bitCount() == 4 assert (-0x33g).bitCount() == 3
Setting, clearing, or flipping bit in virtual sign makes that bit part of the number:
assert (-0x33g).clearBit(9) == -0x233g
We can perform bit-shifting on BigIntegers. The shortcut operators >> and << can't be used, only the method names can be (they're also spelt differently to the fixed-size integer versions of the names, eg, "shiftLeft" instead of "leftShift"). There's no shift-right-unsigned method because this doesn't make sense for BigIntegers with virtual infinite-length sign bits.
assert 0xB4Fg.shiftLeft( 4 ) == 0xB4F0g assert 0xD23Cg.shiftRight( 4 ) == 0xD23g
assert (-0xFFFg).shiftRight( 4 ) == -0x100g
[ 0xABCg, -0x98765g ].each{
it.shiftLeft( 8 ) == it.shiftRight( -8 )
}
We can perform 'not', 'and', 'or', and 'xor' bitwise operations on BigIntegers:
assert 123g.not() == -124g assert -0xFFg.not() == 0x100g
assert ( (0x33g & 0x11g) == 0x11g) && 0x33g.and(0x11g) == 0x11g
assert ( (0x33g | 0x11g) == 0x33g) && 0x33g.or(0x11g) == 0x33g
assert ( (0x33g ^ 0x11g) == 0x22g) && 0x33g.xor(0x11g) == 0x22g
assert 0x33g.andNot(0x11g) == 0x22g && (0x33g & (~ 0x11g)) == 0x22g
For negative numbers:
assert (-1g & -1g) == -1g
assert (1g | -1g) == -1g
assert (1g ^ -1g) == -2g
assert (-1g ^ -2g) == 1g
When the two operands are of different lengths, the sign on the shorter of the two operands is virtually extended prior to the operation:
assert 11g.and(-2g) == 10g