1. Overview
This is an introductory article on the BigDecimal & the BigInteger data types in the Java programming language.
In this write-up, we’ll show in what scenarios we can use these data types.
2. BigDecimal
BigDecimal is the preferred data type when writing code involving money, financial transactions. Also, in situations where precision is a must, and we require a more granular control over rounding off our calculations.
BigDecimal is an immutable data type which provides us two essential features:
- The ability to specify the scale. The scale is the number of digits to the right of the decimal point.
- Providing control over rounding off digits by a rounding off method.
These features are catered to the custom requirements of the developer when writing code dealing with money.
A BigDecimal object can be created like so:
BigDecimal bigDecimal = new BigDecimal("81.9065");
or:
BigDecimal bigDecimal = BigDecimal.valueOf(81.9065);
An enum RoundingMode provides several rounding modes for the BigDecimal type:
- CEILING: Rounding mode to round towards positive infinity
- DOWN: Rounding mode to round towards zero
- FLOOR: Rounding mode to round towards negative infinity
- HALF_DOWN: Rounding mode to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round down
- HALF_EVEN: Rounding mode to round towards the “nearest neighbor” unless both neighbors are equidistant, in which case, round towards the even neighbor
- HALF_UP: Rounding mode to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round up
- UNNECESSARY: Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary
- UP: Rounding mode to round away from zero
Let’s go through a scenario where we set scale & round off the tax values providing a RoundingMode parameter. Here we have two BigDecimal objects serviceTax with an initial value of 56.0084578639 & entertainmentTax with an initial value of 23.00689.
Since our precision for the currency is two digits after the decimal, we provide an argument 2 in the setScale method. The setScale method is used to set the scale for the tax amounts. Along with the set scale argument, rounding off arguments are provided which specify the rule for rounding off the digit:
BigDecimal serviceTax = new BigDecimal("56.0084578639"); serviceTax = serviceTax.setScale(2, RoundingMode.CEILING); BigDecimal entertainmentTax = new BigDecimal("23.00689"); entertainmentTax = entertainmentTax.setScale(2,RoundingMode.FLOOR);
On printing the serviceTax & the entertainmentTax values we see:
serviceTax: 56.01 entertainmentTax: 23.00
The serviceTax amount which was initially 56.0084578639 has been rounded off to 56.01 as per the arguments in the setScale method.
And the entertainmentTax which was originally 23.00689 has been rounded off to 23.00.
+ – * and / the core mathematical operators are not overloaded in the BigDecimal class. It has methods like add(), multiply(), divide() to perform math operations. So now, if we want to sum up serviceTax & the entertainmentTax to get the totalTax we have to use the add() method of the BigDecimal class:
BigDecimal totalTax = serviceTax.add(entertainmentTax);
The totalTax value we get is:
totalTax: 79.01
This pretty much covers the fundamentals of the BigDecimal data type. To learn further about the API, do visit the BigDecimal doc here.
3. BigInteger
BigInteger class in Java is required in mathematical operations where the integer value is large & using the int data type would cause an integer overflow.
BigInteger is used in scenarios where an int just won’t work. For instance, if we calculate the factorial of digit 50 it would come out to be 30414093201713378043612608166064768844377641568960512000000000000. This value is too big for an int data type to handle & can only be stored in a BigInteger variable.
Let’s assume a large numeric value to process, 8731409320171337804361260816606476. Let’s say this number represents the count of stars in our galaxy.
We will now check if this value can be stored in an int variable:
int numStars = 8731409320171337804361260816606476;
As soon as we do this, the compiler complains about it:
“The literal 8731409320171337804361260816606476 of type int is out of range”.
This means the int variable cannot store such a big number. To deal with these scenarios, Java has the BigInteger data type which facilitates storage of such large values.
A BigInteger object can be created as below:
BigInteger numStars = new BigInteger("8731409320171337804361260816606476");
Just like the BigDecimal class BigInteger is an immutable data type. Basic mathematical operators + – * and / are not overloaded.
We have to use methods like add(), multiply(), divide() to perform math operations.
As assumed above, the number of stars in our galaxy the Milky way is 8731409320171337804361260816606476.
Suppose, there is another galaxy Andromeda which has 5379309320171337804361260816606476 stars in it.
Let’s add up the stars of these two galaxies to find out the total stars present.
BigInteger numStarsMilkyWay = new BigInteger("8731409320171337804361260816606476"); BigInteger numStarsAndromeda = new BigInteger("5379309320171337804361260816606476"); BigInteger totalStars = numStarsMilkyWay.add(numStarsAndromeda);
On printing the variable totalStars:
totalStars: 14110718640342675608722521633212952
This sums up the basics of the BigInteger class. Please refer the doc if you need to dig in further.
4. Conclusion
This quick tutorial demonstrated the scenarios where the BigDecimal & the BigInteger data-types would come in handy.
Please find the code for the tutorial over on GitHub.