Primitive type | Size in memory | Value range |
---|---|---|
byte | 8 bit | -128 to 127 |
short | 16 bit | -32768 to 32767 |
char | 16 bit | 0 to 65536 |
int | 32 bits | -2147483648 to 2147483647 |
long | 64 bit | -9223372036854775808 to 9223372036854775807 |
float | 32 bits | (2 to the power of -149) to ((2 to the power of -23) * 2 to the power of 127) |
double | 64 bit | (-2 to the power of 63) to ((2 to the power of 63) - 1) |
boolean | 8 (when used in arrays), 32 (when not used in arrays) | true or false |
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
System.out.println(decimal);
}
}
Passing a string to the constructor is just one possible option.
Here we use strings, because our numbers exceed the maximum values for long and double, and we do need some way to explain to the compiler which number we want to create :)
Simply passing the number
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
to the constructor won't work: Java will try to cram the passed number into one of the primitive data types, but it won't fit into any of them.
That's why using a string to pass the desired number is a good option. Both classes can automatically extract numerical values from the passed strings.
Another important point to remember when working with big-number classes is that their objects are immutable (Immutable).
You're already familiar with immutability thanks to your experience with the String class and the wrapper classes for primitive types (Integer, Long, etc.).
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
integer.add(BigInteger.valueOf(33333333));
System.out.println(integer);
}
}
Console output:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
As you would expect, our number has not changed. To perform the addition operation, you must create a new object to receive the result of the operation.
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigInteger result = integer.add(BigInteger.valueOf(33333333));
System.out.println(result);
}
}
Console output:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
See, now everything works as it should :)
By the way, did you notice how unusual the addition operation looks?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
This is another important point. Big-number classes don't use the + - * / operators. Instead, they provide a set of methods. Let's get acquainted with the main ones (as always, you can find a complete list of methods in the Oracle documentation: here and here).
methods for arithmetic operations: add(), subtract(), multiply(), divide(). These methods are used to perform addition, subtraction, multiplication and division, respectively.
doubleValue(), intValue(), floatValue(), longValue(), etc. are used to convert a big number to one of Java's primitive types. Be careful when using these methods. Don't forget about the differences in bit size!
import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); long result = integer.longValue(); System.out.println(result); } }
Console output:
8198552921648689607
min() and max() let you find the minimum and maximum value of two big numbers.
Note that these methods are not static!import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); System.out.println(integer.max(integer2)); } }
Console output:
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
BigDecimal rounding behavior
This topic has its own separate section, since rounding big numbers and configuring rounding behavior are not so simple. You can use the setScale() method to set the number of decimal places for a BigDecimal. For example, suppose we want the number 111.5555555555 to have three digits after the decimal point. However, we can't achieve what we want by passing the number 3 as an argument to the setScale() method. As mentioned above, BigDecimal is for representing numbers with strict requirements on computational precision. In its current form, our number has 10 digits after the decimal point. We want to drop 7 of them and keep only 3. Accordingly, in addition to the number 3, we must pass the rounding mode. BigDecimal has a total of 8 rounding modes. That's a lot! But if you really need to fine tune the precision of your calculations, you'll have everything you need. So, here are the 8 rounding modes offered by BigDecimal:ROUND_CEILING — rounds up
111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
ROUND_DOWN — rounds towards zero
111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
ROUND_FLOOR — rounds down
111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
ROUND_HALF_UP — rounds up if the number after the decimal point >= 0.5
0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
ROUND_HALF_DOWN — rounds up if the number after the decimal point > 0.5
0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
ROUND_HALF_EVEN — rounding depends on the number to the left of the decimal point. If the number to the left is even, rounding will be down. If the number to the left of the decimal point is odd, then rounding will be up.
2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
The number to the left of the decimal place is 2 (even). The number is rounded down. We want 0 decimal places, so the result is 2.
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
The number to the left of the decimal point is 3 (odd). The number is rounded up. We want 0 decimal places, so the result is 4.
ROUND_UNNECCESSARY — This mode is used when you must pass a rounding mode to a method, but the number does not need to be rounded. If you try to round a number with the ROUND_UNNECCESSARY mode set, an ArithmeticException is thrown.
3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
ROUND_UP — rounds away from zero.
111.5551 -> setScale(3, ROUND_UP) -> 111.556
Comparing big numbers
This is also important. You will recall that we use the equals() method is compare objects in Java. The implementation is either provided by the language itself (for standard Java classes) or overriden by the programmer. But in the case of BigDecimal objects, using the equals() method for comparisons is not recommended. This is because the BigDecimal.equals() method returns true only if the 2 numbers have the same value and scale: Let's compare the behavior of the equals() method for the Double and BigDecimal classes:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Double a = 1.5;
Double b = 1.50;
System.out.println(a.equals(b));
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.equals(y));
}
}
Console output:
true
false
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.compareTo(y));
}
}
Console output:
0
The compareTo() method returned 0, which means that 1.5 and 1.50 are equal. And this is the result we expected! :) That concludes our lesson today. Now it's time to get back to the tasks! :)
GO TO FULL VERSION