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:
Integers will normally be the smallest type into which the value will fit (using 2's-complement representation):
We can represent integers in base-10, hexadecimal, or octal notation:
We can negate hexadecimals and octals to represent negative numbers.
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:
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.
We can enquire the bit-size of each type of fixed-size integer:
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:
The fixed-size integer classes can be converted to one another:
We can create new fixed-sized integers from strings:
To convert from a fixed-size integer to a string in various bases:
If the base/radix isn't between Character.MIN_RADIX and Character.MAX_RADIX, base 10 is used instead:
The common bases have similar methods which always return an unsigned integer:
We can convert a string representation to an integer, using a specified base/radix:
A NumberFormatException may be thrown:
An alternative method name is:
We can convert a string to a fixed-size integer, similar to parseInt() etc, but with the radix instead indicated inside the string:
We can return an integer representing the sign:
We can compare fixed-size integers with each other:
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:
Not all calculations have a special operator symbol:
We can increment and decrement variables, using operators, either before and after evaluation:
Rules of parentheses and precedence apply to these operators. The operators have the same precedence irrespective of what type of values they operate on.
Integers often convert their types during math operations. For + - *, a Long with an Integer converts the Integer to a 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:
We can compare fixed-size integers using < <= > >= operators, of lower precedence than addition/etc:
The operators == != <=> are of lower precedence than the other comparison operators:
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:
To return the number of zero bits preceding the highest-order 1-bit:
We can perform a bitwise complement of the bits in a fixed-size integer using the ~ operator:
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.
We can rotate the bits in an integer or long:
We can perform bitwise 'and', 'or', and 'xor' operations on fixed-size integers. This is of lower precedence than the comparison operators.
We can reverse the bits or bytes of the binary representation of an int or long:
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:
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:
We can use the conditional operator ?:, of lower precedence than the boolean operators, to choose between two values:
We can put the assignment operator = within expressions, but must surround it with parentheses because its precedence is lower than the conditional:
Of equal precedence as the plain assignment operator = are the quick assignment *= += -= %= **= <<= >>= >>>= &= ^= |= operators:
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:
A method and some fields that give a little more efficiency:
We can construct a BigInteger using an array of bytes:
We can convert a BigInteger back to an array of bytes:
We can pass in a string in a certain base/radix:
We can convert the BigInteger back to a string:
We can construct a randomly-generated BigInteger:
Arithmetic with BigIntegers
We can perform the usual arithmetic operations + - * using either methods or operations:
For + - *, a BigInteger causes any fixed-width integers in the calculation to be converted to a 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:
We can also increment and decrement BigIntegers:
We can find out the quotient and remainder:
Other methods for arithmetic:
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:
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.
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:
More bit-manip methods:
Setting, clearing, or flipping bit in virtual sign makes that bit part of the number:
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.
We can perform 'not', 'and', 'or', and 'xor' bitwise operations on BigIntegers:
For negative numbers:
When the two operands are of different lengths, the sign on the shorter of the two operands is virtually extended prior to the operation: