When using BigDecimal's division method, I encountered a ghost animal problem. Originally, I thought the accuracy was calculated, and the result returned 0. Of course, it was finally found that the posture was wrong. Therefore, record it to avoid repeating the mistakes later
1. Problem throw
When using BigDecimal to do high-precision division, I accidentally encountered a small problem, as shown below
@Test public void testBigDecimal() { BigDecimal origin = new BigDecimal(541253); BigDecimal now = new BigDecimal(12389431); BigDecimal val = origin.divide(now, RoundingMode.HALF_UP); System.out.println(val); origin = new BigDecimal(541253); now = new BigDecimal(12389431.3); val = origin.divide(now, RoundingMode.HALF_UP); System.out.println(val); origin = new BigDecimal(541253.4); now = new BigDecimal(12389431); val = origin.divide(now, RoundingMode.HALF_UP); System.out.println(val); } Copy code
What is the output above?
0 0 0.043686703610520937021487456961257 Copy code
Why are the first two 0? It's understandable if 541253 / 12389431 = 0 directly, but BigDecimal is not a high-precision calculation. It's reasonable that there should be no such problem of division
We know that when BigDecimal is triggered, you can specify the parameter to keep decimal. If you add this, will it be different?
BigDecimal origin = new BigDecimal(541253); BigDecimal now = new BigDecimal(12389431); BigDecimal val = origin.divide(now, 5, RoundingMode.HALF_UP); System.out.println(val); Copy code
The output result is:
0.04369 Copy code
Therefore, there is no problem after the decimal point is specified. So let's make a bold guess. In the above case s, when the scale value is not specified, the default value is different, resulting in different accuracy of the final result?
After a simple in-depth analysis of the source code, the execution method is origin.divide(now, RoundingMode.HALF_UP);, Therefore, the scale parameter is aimed at the origin object, and this object can only analyze its structure, because there is no other place to use it
2. Source location
1. Shaping parameter transmission structure
Analyze the following line and go directly to the source code
BigDecimal origin = new BigDecimal(541253); Copy code
Obviously, the int parameter passing structure. Go in and have a simple look
// java.math.BigDecimal#BigDecimal(int) public BigDecimal(int val) { this.intCompact = val; this.scale = 0; this.intVal = null; } public BigDecimal(long val) { this.intCompact = val; this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null; this.scale = 0; } Copy code
so, it is clear that the default scale is 0, that is, when the origin is a positive number, the division is performed by it. It is unrealistic to specify the scale parameter, and the final return is no decimal. Similarly, take a look at the parameter transmission method of long, and BigInteger is the same
2. Floating point parameter transfer
The next step is to confirm the default value of floating-point scale. This structure is a little more complex than the previous one. The source code is not pasted. It is too long and you can't understand what you have done. You can directly enter the debug mode in a more obscene way and execute it step by step
@Test public void testBigDecimal() { BigDecimal origin = new BigDecimal(541253.0); BigDecimal now = new BigDecimal(12389431.1); BigDecimal tmp = new BigDecimal(0.0); } Copy code
According to the result of debug, the first scale is 0; The second scale is 29 and the third scale is 0



3. String parameter transfer
It is still a large string of logic. Try the same way with one-step debug
@Test public void testBigDecimal() { BigDecimal origin = new BigDecimal("541253.0"); BigDecimal now = new BigDecimal("12389431.1"); BigDecimal t = new BigDecimal("0.0"); } Copy code
The scale of the above three is 1

4. Summary
- For BigDecimal, it is best to specify its scale parameter when performing division operation, otherwise there may be pits
- For the principle of BigDecimal's scale initialization, we need to take an in-depth look at how BigDecimal is implemented
Finally, a graph of multiplication is pasted as a conclusion

Series blog posts:
- Practical tips 1: String placeholder replacement - JDK version
- Practical tips 2: conversion between array and list
- Practical tips 3: conversion between string and container
- Practical tips 4: elegant string splicing
- Practical tips 5: hump and underline turn each other
- Practical tips 6: special usage of enumeration
- Practical tips 7: be careful in sorting
- Practical tip 8: specify the initialization size of the container
- Practical tips 9: improper use of List.subList StackOverflowError
- Practical tip 10: immutable container
- Practical tips 11: array copy
- Practical tips 12: number formatting
- Practical tips 13: hexadecimal conversion is very simple
- Practical tips 14: configuration file Properties
- Practical tips 15: how to determine whether a class is a basic type or a packaging class of a basic type
- Practical tips 17: how to choose random number generation
2. Other
1. A gray Blog: liuyueyi.github.io/hexblog
If you believe in a book, it's better to have no book. It's just the words of a family. Due to your limited personal ability, it's inevitable to have omissions and mistakes. If you find a bug or have better suggestions, you're welcome to criticize and correct and appreciate it