Explain BigDecimal in detail

Table of contents

1 Overview

2. Basic API

2.1. Create a BigDecimal object:

2.3. Basic operation method:

2.4. Precision control method:

2.5. Comparison

2.6. Conversion

3. Precautions

4. The underlying implementation principle


1 Overview

Loss of precision, since floating-point numbers are used to represent decimals in modern computers, there will be a problem of loss of precision in this representation. If you want to understand the reason for the loss of precision, you can read another article by the blogger, which explains the reason in detail:

Detailed explanation of floating point numbers__BugMan's Blog - CSDN Blog

Here is an example of loss of precision:

// 商品价格
double price1 = 19.99;
double price2 = 9.99;
double price3 = 4.99;

// 商品数量
int quantity1 = 2;
int quantity2 = 3;
int quantity3 = 1;

// 计算每种商品的小计
double subtotal1 = price1 * quantity1;
double subtotal2 = price2 * quantity2;
double subtotal3 = price3 * quantity3;

// 计算总价
double total = subtotal1 + subtotal2 + subtotal3;

// 输出结果
System.out.println("商品1小计:" + subtotal1);
System.out.println("商品2小计:" + subtotal2);
System.out.println("商品3小计:" + subtotal3);
System.out.println("购物车总价:" + total);

Take out the mobile phone and calculate it, the original total price should be equal to 74.94, but the actual running result is equal to: 

This loss of precision is unacceptable in scenarios that require high-precision calculations, such as finance and aerospace. In order to ensure precision, JDK introduces the BigDecimal type for precise calculation of floating-point numbers. After changing the above example to BigDecimal:

// 商品价格
BigDecimal price1 = new BigDecimal("19.99");
BigDecimal price2 = new BigDecimal("9.99");
BigDecimal price3 = new BigDecimal("4.99");
        
// 商品数量
int quantity1 = 2;
int quantity2 = 3;
int quantity3 = 1;
        
// 计算每种商品的小计
BigDecimal subtotal1 = price1.multiply(new BigDecimal(quantity1));
BigDecimal subtotal2 = price2.multiply(new BigDecimal(quantity2));
BigDecimal subtotal3 = price3.multiply(new BigDecimal(quantity3));
        
// 计算总价
BigDecimal total = subtotal1.add(subtotal2).add(subtotal3);
        
// 输出结果
System.out.println("商品1小计:" + subtotal1);
System.out.println("商品2小计:" + subtotal2);
System.out.println("商品3小计:" + subtotal3);
System.out.println("购物车总价:" + total);

result:

2. Basic API

2.1. Create a BigDecimal object:

  • BigDecimal(String val): Creates a BigDecimal object using a string representation.

  • BigDecimal(double val): Creates a BigDecimal object using a double-precision floating-point number.

  • BigDecimal(BigInteger val): Creates a BigDecimal object using a BigInteger object.

BigDecimal bigDecimal1=new BigDecimal("0.8");
BigDecimal bigDecimal2=new BigDecimal(0.8);
BigDecimal bigDecimal3=new BigDecimal(8);

2.3. Basic operation method:

  • add(BigDecimal augmentend): addition operation, add the current BigDecimal object to the parameter.

  • subtract(BigDecimal subtrahend): subtraction operation, which subtracts the parameter from the current BigDecimal object.

  • multiply(BigDecimal multiplicand): multiplication operation, multiply the current BigDecimal object with the parameter.

  • divide(BigDecimal divisor): division operation, divide the current BigDecimal object by the parameter.

  • pow(int exponent): Exponential operation, calculate the power of the current BigDecimal object.

BigDecimal bigDecimal1=new BigDecimal("0.8");
BigDecimal bigDecimal2=new BigDecimal("0.2");
System.out.println(bigDecimal1.add(bigDecimal2));
System.out.println(bigDecimal1.multiply(bigDecimal2));
System.out.println(bigDecimal1.divide(bigDecimal2));
System.out.println(bigDecimal1.pow(2));

2.4. Precision control method:

  • setScale(int newScale): Set the precision of the BigDecimal object (number of digits after the decimal point).

  • setScale(int newScale, RoundingMode roundingMode): Set the precision of the BigDecimal object and specify the rounding mode.

  • round(MathContext mc): Rounds the current BigDecimal object using the specified rounding rules.

BigDecimal number = new BigDecimal("123.456789");
BigDecimal roundedNumber = number.setScale(2, BigDecimal.ROUND_HALF_UP);

2.5. Comparison

  • compareTo(BigDecimal val): Compare the size relationship between the current BigDecimal object and the parameter.

  • equals(Object obj): compares whether the current BigDecimal object is equal to the parameter.

BigDecimal bigDecimal1 = new BigDecimal("123.456789");
BigDecimal bigDecimal2 = new BigDecimal("123.456789");
System.out.println(bigDecimal1.compareTo(bigDecimal2));
System.out.println(bigDecimal1.equals(bigDecimal2));

2.6. Conversion

  • intValue(), longValue(), floatValue(), doubleValue(): convert the BigDecimal object to the corresponding basic data type.

  • toBigInteger(), toBigIntegerExact(): Convert BigDecimal objects to BigInteger objects.

BigDecimal bigDecimal = new BigDecimal("123.456789");
int i = bigDecimal.intValue();
float v = bigDecimal.floatValue();
double v1 = bigDecimal.doubleValue();
long l = bigDecimal.longValue();
BigInteger bigInteger = bigDecimal.toBigInteger();
BigInteger bigInteger1 = bigDecimal.toBigIntegerExact();

3. Precautions

Although BigDecimal can prevent the loss of precision during the operation process, it cannot prevent the loss of precision during the initialization process, for example:

BigDecimal bigDecimal1=new BigDecimal(1.2);
BigDecimal bigDecimal2=new BigDecimal(1.234);
System.out.println(bigDecimal1.add(bigDecimal2));

The above code will have precision loss, because after we input 1.2 and 1.234, the input data will be converted to floating-point numbers and stored in the memory of the computer. During this conversion process, the precision has been lost, and BigDecimal reads these two numbers in the memory. When , what is read out is the number with loss of precision.

To ensure precision, try to initialize with a string:

BigDecimal bigDecimal1=new BigDecimal("1.2");
BigDecimal bigDecimal2=new BigDecimal("1.234");
System.out.println(bigDecimal1.add(bigDecimal2));

4. The underlying implementation principle

The underlying code of BigDecimal is not very readable. Here is a summary of the underlying implementation principles:

Internally, BigDecimal uses an array of integers to store each digit of the value. Typically, each element of the array represents a set of decimal digits, for example, the first element of the array represents the lowest digit, the second element represents the tens digit, and so on. Each array element is a 32-bit integer, which can store a value between 0 and 2^32-1.

In order to represent a value, BigDecimal also needs to maintain some other information, including the sign (positive, negative or zero), the position of the decimal point, and the precision of the value. This information is stored in additional variables.

When performing numerical operations, BigDecimal performs corresponding operations on two numerical values, such as addition, subtraction, multiplication, and division, according to the type of operation and the required precision. During the operation, it processes the symbols of the two values ​​and operates according to the mathematical rules. For division operations, BigDecimal will perform calculations through precise algorithms, avoiding the loss of precision that may be caused by floating-point number division.

Guess you like

Origin blog.csdn.net/Joker_ZJN/article/details/131341354