What is BigDecimal
BigDecimal can represent a floating point number of any size with complete accuracy.
Why use BigDecimal instead of double
Talk is cheap, Show me the Code.
Example 1:
double d1 = 0.3; double d2 = 0.2; System.out.println("Double:\t 0,3 - 0,2 = " + (d1 - d2)); float f1 = 0.3f; float f2 = 0.2f; System.out.println("Float:\t 0,3 - 0,2 = " + (f1 - f2)); BigDecimal bd1 = new BigDecimal("0.3"); BigDecimal bd2 = new BigDecimal("0.2"); System.out.println("BigDec:\t 0,3 - 0,2 = " + (bd1.subtract(bd2)));
Run Results
Double: 0,3 - 0,2 = 0.09999999999999998 Float: 0,3 - 0,2 = 0.10000001 BigDec: 0,3 - 0,2 = 0.1
From the results, BigDecimal is required when we want to perform precise decimal operations.Now let's divide and see what happens:
Example 2:
double d1 = 10; double d2 = 3; System.out.println("Double:\t 10 / 3 = " + (d1 / d2)); float f1 = 10f; float f2 = 3f; System.out.println("Float:\t 10 / 3 = " + (f1 / f2)); // Exception! BigDecimal bd3 = new BigDecimal("10"); BigDecimal bd4 = new BigDecimal("3"); System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4)));
Run Results
Double: 10 / 3 = 3.3333333333333335 Float: 10 / 3 = 3.3333333 Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
An exception is thrown when the result is excluded and the carry status value is not set.The correct operation is as follows:
System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4,4,BigDecimal.ROUND_HALF_UP)));
Run Results
Double: 10 / 3 = 3.3333333333333335 Float: 10 / 3 = 3.3333333 BigDec: 10 / 3 = 3.3333
Summary: When we have a very high accuracy requirement, we need to make precise calculations, such as currency, so we need to use the java.math.BigDecimal class for precise calculations.
Add, subtract, multiply and divide
Method | Narration |
---|---|
add(BigDecimal) | Add the values in the BigDecimal object and return it |
subtract(BigDecimal) | Subtract the values in the BigDecimal object and return it |
multiply(BigDecimal) | Multiply the values in the BigDecimal object and return the object |
divide(BigDecimal) | Divide the values in the BigDecimal object and return it |
public class BigDecimalCalculation { static BigDecimal a = new BigDecimal("0.02"); static BigDecimal b = new BigDecimal("0.03"); public static void main(String[] args) { System.out.println("a + b = " + a.add(b)); System.out.println("a - b = " + a.subtract(b)); System.out.println("a * b = " + a.multiply(b)); System.out.println("a ÷ b = " + a.divide(b,2,BigDecimal.ROUND_HALF_UP)); } }
Run result:
a + b = 0.05 a - b = -0.01 a * b = 0.0006 a ÷ b = 0.67
common method
Keep two decimal places
public class keepTwoDecimal { public static void main(String[] args) { BigDecimal num= new BigDecimal(13.154215); //Mode 1 DecimalFormat df1 = new DecimalFormat("0.00"); String str = df1.format(num); System.out.println(str); //13.15 //Mode 2 // #.00 means two decimal digits#.0000 four decimal digits DecimalFormat df2 =new DecimalFormat("#.00"); String str2 =df2.format(num); System.out.println(str2); //13.15 //Mode 3 //%.2f%.indicates that any number of digits before the decimal point 2 indicates two decimal places formatted as f indicates floating point type String result = String.format("%.2f", num); System.out.println(result); //13.15 } }
Rounding
- ROUND_UP
Rounding mode away from zero.
Always increase the number before discarding non-zero parts (always add 1 to the number before non-zero discarded parts)
For example: 2.36 -> 2.4
- ROUND_DOWN
Rounding mode near zero.
Never add a number until a part is discarded (never add 1, or truncate, to the number before the discarded part).
For example: 2.36 -> 2.3
- ROUND_CEILING
Rounding pattern approaching positive infinity.
If BigDecimal is positive, the rounding behavior is the same as ROUND_UP;
If negative, the rounding behavior is the same as ROUND_DOWN.
Equivalent to a combination of ROUND_UP and ROUND_DOWN
- ROUND_FLOOR
Rounding pattern near negative infinity.
If BigDecimal is positive, the rounding behavior is the same as ROUND_DOWN;
If negative, the rounding behavior is the same as ROUND_UP.
Contrary to ROUND_CEILING
- ROUND_HALF_UP
Rounding
For example: 2.35 -> 2.4
- ROUND_HALF_DOWN
Rounding
For example: 2.35 -> 2.3
- ROUND_HALF_EVEN
If the number to the left of the discarded part is odd, the rounding behavior is the same as ROUND_HALF_UP (rounding);
If it is even, the rounding behavior is the same as ROUND_HALF_DOWN (rounding).
For example: 1.15 -> 1.1, 1.25 -> 1.2
- ROUND_UNNECESSARY
Asserting that the requested operation has precise results does not require rounding.
ArithmeticException is thrown if this rounding mode is specified for operations that produce accurate results.
I think it's OK to know what's left, and I feel that what's left is wrong, like ROUND_HALF_DOWN and ROUND_HALF_EVEN. Look at the results below and you will know why I'm saying it.
public class BigDecimalScaleTest { public static void main(String[] args) { double num = 2.35; BigDecimal b = new BigDecimal(num); // setScale(1) indicates reserving a decimal place System.out.println("ROUND_UP,Result:" + b.setScale(1, BigDecimal.ROUND_UP).doubleValue()); System.out.println("ROUND_DOWN,Result:" + b.setScale(1, BigDecimal.ROUND_DOWN).doubleValue()); System.out.println("ROUND_CEILING,Result:" + b.setScale(1, BigDecimal.ROUND_CEILING).doubleValue()); System.out.println("ROUND_FLOOR,Result:" + b.setScale(1, BigDecimal.ROUND_FLOOR).doubleValue()); System.out.println("ROUND_HALF_UP,Result:" + b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue()); System.out.println("ROUND_HALF_DOWN,Result:" + b.setScale(1, BigDecimal.ROUND_HALF_DOWN).doubleValue()); System.out.println("ROUND_HALF_EVEN,Result:" + b.setScale(1, BigDecimal.ROUND_HALF_EVEN).doubleValue()); System.out.println("ROUND_UNNECESSARY,Result:" + b.setScale(1, BigDecimal.ROUND_UNNECESSARY).doubleValue()); } }
Run Results
ROUND_UP,Results: 2.4 ROUND_DOWN,Results: 2.3 ROUND_CEILING,Results: 2.4 ROUND_FLOOR,Results: 2.3 ROUND_HALF_UP,Results: 2.4 ROUND_HALF_DOWN,Results: 2.4 (Come and explain this to me. What about rounding?) ROUND_HALF_EVEN,Results: 2.4 (And this one) Disconnected from the target VM, address: '127.0.0.1:59637', transport: 'socket' Exception in thread "main" java.lang.ArithmeticException: Rounding necessary
Summary: The usual ones are ROUND_HALF_UP, ROUND_UP and ROUND_DOWN, just the other jokes.
compare
a.compareTo(b)
A > B returns 1; a = b returns 0; a < B returns -1
public class BigDecimalCompare { public static void main(String[] args) { BigDecimal a = new BigDecimal("0.02"); BigDecimal b = new BigDecimal("0.01"); BigDecimal a2 = new BigDecimal("0.02"); System.out.println(" a > b Return results:" + a.compareTo(b)); System.out.println(" a = a2 Return results:" + a.compareTo(a2)); System.out.println(" b < a Return results:" + b.compareTo(a)); } }
Run Results
A > b Returns: 1 a = a2 Returns: 0 B < a Returns: -1
Matters needing attention
In the above use, we all use String to assign BigDecimal instead of using the double type. See the following example for specific reasons:
public class BigDecimalTest { public static void main(String[] args) { BigDecimal num1 = new BigDecimal(0.005); BigDecimal num2 = new BigDecimal(1000000); BigDecimal num3 = new BigDecimal(-1000000); //Initialize as strings as possible BigDecimal num12 = new BigDecimal("0.005"); BigDecimal num22 = new BigDecimal("1000000"); BigDecimal num32 = new BigDecimal("-1000000"); //addition BigDecimal result1 = num1.add(num2); BigDecimal result12 = num12.add(num22); //subtraction BigDecimal result2 = num1.subtract(num2); BigDecimal result22 = num12.subtract(num22); //multiplication BigDecimal result3 = num1.multiply(num2); BigDecimal result32 = num12.multiply(num22); //absolute value BigDecimal result4 = num3.abs(); BigDecimal result42 = num32.abs(); //division BigDecimal result5 = num2.divide(num1,20,BigDecimal.ROUND_HALF_UP); BigDecimal result52 = num22.divide(num12,20,BigDecimal.ROUND_HALF_UP); System.out.println("Addition value Result:"+result1); System.out.println("Addition string Result:"+result12); System.out.println("subtraction value Result:"+result2); System.out.println("Subtraction string Result:"+result22); System.out.println("Multiplication value Result:"+result3); System.out.println("Multiplication string Result:"+result32); System.out.println("Absolute value in value Result:"+result4); System.out.println("Absolute value in string Result:"+result42); System.out.println("Division value Result:"+result5); System.out.println("Division string Result:"+result52); } }
Run result:
Addition value result: 1000000.0050000000000001040855860842566454688835404296875 string result for addition: 1000000.005 Subtraction value result: -999999.99499999999999999999999999998959165914413915743352845311185595703125 string result for subtraction: -999999.995 Multiplication value result: 5000.000000000104085586084256645468883514404296875000000 Multiplication string result: 5000.000 Absolute value with value result: 1000000 string result for absolute value: 1000000 value result for division: 1999999.99999999995836665766 string result for division: 200000000.00000000000000000
- Numbers in System.out.println() are of type double by default, and decimal calculations of type double are inaccurate
- When passed in the double type using the BigDecimal construction method, the result of the calculation is also inaccurate!
So when we assign values using BigDecimal, it's best to use the constructor passed in to the String to confirm accuracy.
Reference resources
https://blog.csdn.net/haiyins...