JavaRush /Java Blog /Random EN /BigInteger and BigDecimal

BigInteger and BigDecimal

Published in the Random EN group
In Java, an application is made up of classes, and classes are made up of methods and variables. Variables, in turn, are divided into primitive and reference. BigInteger and BigDecimal - 1There are 8 types of variables in Java and, excluding booleanand char, they are divided into the following types:
  • integers: byte, short, intand long;
  • floating point (also called real numbers): floatand double.
Within these small groups, differences exist only in the range of values ​​that can be contained (and, accordingly, the occupied space of such a variable varies). The largest of the integer types is long, with a range from -9223372036854775808 to 9223372036854775807. Of the floating point numbers, double, with a range of 1.7e-308 to 1.7e+308. You can read more about real numbers in this article . But what if we need to store numbers that are larger than the acceptable range? In this case, we will need BigIntegerand BigDecimal.

BigInteger in Java

The Java class BigIntegeris used as an analogue to arbitrary-length integer values ​​that does not have the 64-bit limit of long. Moreover, it is a descendant of the class Number, like standard wrappers for numeric simple types - Integer, Long, Byte, Doubleand so on - therefore it has implementations of methods leading to simple types:
BigInteger value = new BigInteger("32145");

int intValue = value.intValue();//32145

long longValue = value.longValue();//32145

double doubleValue = value.doubleValue();//32145.0
Immediately we see the creation of such an object BigIntegerwith our value being passed to the constructor, but in string format. It is worth noting that he has more than one designer, but for all occasions. If primitive types do not accommodate the full amount of data from BigInteger, the data will be truncated to the range of that primitive type. But at the same time, there are analogues of these methods ( intValueExact(), longValueExact()etc.), with the only difference being that if the simple type to which the conversion is taking place does not accommodate the data range, an ArithmeticException is thrown .

BigInteger constants

For internal use, the class has constants:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
These are constant objects BigIntegerwith values, respectively, 0, 1and 10.

BigInteger Methods

One of the main features of this class is that it is full of methods that implement standard arithmetic operations in Java. For example:
  • summation operations:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • multiplication operations:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • operations of finding the remainder when dividing one number by another:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • getting the absolute value of a number (that is, modulo, unsigned):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
There are also methods for more complex (specific) operations:
  • operations with mod calculation :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
There are several different variations of this function:
  • obtaining a random number and specifying the number of bits that the resulting value will use:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • bitwise shift operations(this >> n)

    Shift left:

    BigInteger firstValue = new BigInteger("5");
    BigInteger firstResultValue = firstValue.shiftLeft(3);//40

    Shift right:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
Of course, it is better to look at the full list of methods in the documentation . BigInteger and BigDecimal - 2

BigDecimal in Java

When we need a real number of arbitrary length, the Java class is used - BigDecimal. As a rule, it is used to work with finances instead of double, as it gives more customization options. Like and BigInteger, BigDecimalis a descendant of a class Numberand has methods that return the value of an object as a specific primitive type:
BigDecimal value = new BigDecimal(35563.3);

long longValue = value.longValue();//35563

double doubleValue = value.doubleValue();//35563.3
As we can see when reducing to long, only the integer part remains, and the decimal places are discarded.

BigDecimal constructors

We will take a closer look at the constructors BigDecimal, since the class has a much wider selection of them. There are constructors that allow you to set the value of an object in different ways (by passing int, long, double, Stringand even BigInteger), and there are those that allow it. set the settings of the created object (rounding methods, number of decimal places):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Everything is clear here, we directly set the value and number of decimal places we want to see.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
The results of this constructor can be quite unpredictable, because we are specifying double, which by its nature is a very ambiguous type. Therefore, it is generally recommended to use in a constructor String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
We set double, but at the same time we also set a parameter that describes the rounding rule (which contains the number of decimal places and the algorithm for rounding).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
We set an array of characters from which element we take the values ​​for the object and how many of these elements we take.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
We take an already existing object BigInteger, set the number of decimal places.

BigDecimal Methods

The class BigDecimalalso contains methods for various arithmetic operations, but BigIntegerit does not have methods for working with bits, like . But nevertheless, the main feature BigDecimalis the flexibility in working with floating point numbers. Let's look at some techniques that give us the power to master the real numbers:
  • we get the precision (number of numbers):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • set the number of decimal places and the rounding rule:

    BigDecimal firstValue = new BigDecimal(3445.544445);
    
    BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545

    Below we will take a closer look at the constants for setting rounding rules.

  • divide BigDecimalby another BigDecimal, while indicating the required number of decimal places and the rounding rule:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • moving a decimal point right/left by a certain number of places:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • trim trailing zeros:

    BigDecimal value = new BigDecimal("45056.5000");
    BigDecimal result = value.stripTrailingZeros();//45056.5

    If we have all zeros in the real part and there are also zeros in the whole part (or we have no decimal places at all), then:

    BigDecimal value = new BigDecimal("450000.000");
    BigDecimal result = value.stripTrailingZeros();//4.5E+5

BigDecimal rounding rules

To set rounding rules, inside BigDecimalwe can see special constants that describe rounding algorithms: ROUND_UP- rounding from zero, rounding towards the real part:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN— rounding to zero, that is, truncation of the real part:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_DOWN  );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN  );//-2.6
ROUND_CEILING— rounding to positive infinity. That is, if our number is positive, then -> ROUND_UP, if negative, then ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR- rounding to negative infinity, that is, if our number is positive, then -> ROUND_DOWN, if negative, then ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
For the value under consideration, we will consider this nearest number with a truncated decimal place as the nearest neighbor of the number under consideration. For example, 2.43 will be closer to 2.4 than 2.5, but 2.48 will be closer to 2.5. ROUND_HALF_DOWN— rounding to the “nearest neighbor”. If both neighbors are equidistant from a particular value, then round to zero is performed. Equidistant is, for example, when the number being rounded is 5, and it is the same distance from 0 and 10):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP— mode for rounding towards the “nearest neighbor”. If both neighbors are equidistant, rounding up is done (this is the same rounding we were taught in school):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.6
ROUND_HALF_EVEN— rounding to the “nearest neighbor” if both neighbors are not equidistant. In this case, if the number being rounded is preceded by an odd number, it is rounded up, and if it is even, it is rounded down:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
We get this result because when rounding, 5 looks at the previous number 2, and seeing that it is even, rounds down. But if:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
That rounding goes up, since the last 5 looks at the previous value and sees an odd number. As a result, the number is rounded up to 6, after which the next 6 is also rounded. But the six no longer looks at the number on the left, since the number is clearly closer upward, and as a result the last 2 is increased by 1. ROUND_UNNECESSARY- used to check that the number does not need to be rounded. That is, we check that the number has the required number of decimal places:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Everything is fine here, the value has two digits and we check that there are only two digits after the decimal point. But if:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Then we get - ArithmeticException, since the value being tested exceeds the specified number of decimal places. But if we check two decimal places, but in fact there is one there, then the exception will not be thrown, and the missing digits are simply supplemented with zeros:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
I would also like to note that y BigDecimalhas constants similar to the constants BigInteger ZERO, ONEand TEN. Here is a link to the documentation . And finally: as you probably noticed, when performing operations with objects BigIntegerand BigDecimal, we do not change the old ones, but always get new ones. This tells us that they are immutable, that is, unchangeable after their creation, just like String. In other words, all their methods cannot change the internal state of the object; at most, they can return a new object with the parameters specified by the function we are using.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION