Location>code7788 >text

The production environment BigDecimal is used incorrectly and has been crying in the toilet.

Popularity:947 ℃/2024-12-10 15:32:27

Hello, I'm Suzan and I'm meeting you all again.

preamble

In daily development, many partners like to use BigDecimal to deal with precise calculations, such as money, fractions, proportions and so on.

Theoretically, it's more precise than double or float, but if you use it incorrectly, the loss of precision can make you cry.

Today we are going to talk about , 6 scenarios of using BigDecimal incorrectly, why the problem occurs, and how to avoid the problem, hopefully it will be helpful to you.

1 Direct initialization with floating point numbers

Quite a few of my buddies are used to writing this way:

BigDecimal num = new BigDecimal(0.1);
(num); 

Print result: 0.1000000000000000055511151231257827021181583404541015625

Not printed: 0.1

What's the problem?

This is not a problem with BigDecimal, but with floating point numbers themselves.

In Java, the precision of double is limited, 0.1 converted to binary is an infinite loop decimal, directly passed in will bring error.

The correct posture is to pass a string:

BigDecimal num = new BigDecimal("0.1");
(num); 

Print result: 0.1, which is correct.

Note: Never use the BigDecimal(double) constructor, it is more reliable to use a string or integer. You can also use the () function.

2 Addition, subtraction, multiplication and division without precision

Some little ones do addition, subtraction, multiplication and division by writing directly:

BigDecimal a = new BigDecimal("1.03");
BigDecimal b = new BigDecimal("0.42");
//subtractive
BigDecimal result = (b);
(result);

Print result:: 0.61, no problem.

But the problem is in the division:

BigDecimal c = new BigDecimal("10");
BigDecimal d = new BigDecimal("3");
BigDecimal result = (d); 

The run just blew up.:: Non-terminating decimal expansion

The root cause of the error: 10/3 is an infinite number of decimals, BigDecimal doesn't keep the decimal point by default, and the precision is overflowed.

So, how do we optimize?

A: Add a MathContext or specify the precision.

Example:

BigDecimal result = (d, 2, RoundingMode.HALF_UP);
(result); 

Printed result: 3.33, which works fine.

Therefore, we need to be aware that when doing division in BigDecimal, the precision must be specified.

3 Determining equality with equals

BigDecimal's equals compares value and precision, which has screwed a lot of people:

BigDecimal x = new BigDecimal("1.0");
BigDecimal y = new BigDecimal("1.00");

((y)); 

Print result: false.

Although the values of 1.0 and 1.00 are equal, the precision is not the same and equals is judged as different.

Optimized method to compare values using compareTo:

Example:

((y) == 0); 

Print result: true

One thing to note is that we should use the compareTo method, not the equals method, when determining whether two BigDecimal objects are equal.

4 Ignoring practical implications when using scale

Some of you guys can't figure out the difference between scale (number of decimal places) and precision (total number of places) and write directly:

BigDecimal num = new BigDecimal("123.4500");
(()); 

Printed results: 4

But if you write it like the following:

BigDecimal stripped = ();
(()); 

The printout is: 2

The scale will change, and if it does, it will affect subsequent calculations.

So, how do we optimize our approach?

A: Define the meaning of scale.

To fix the decimal places, use setScale:

BigDecimal fixed = (2, RoundingMode.HALF_UP);
(fixed); 

Printed result: 123.45.

Let's not confuse scale with precision, and set the number of decimal places explicitly if necessary.

5 Ignoring immutability

BigDecimal is immutable, but some peeps will write it this way:

BigDecimal sum = new BigDecimal("0");
for (int i = 0; i < 5; i++) {
    (new BigDecimal("1"));
}

Print result: 0

The reason for the problem is that the add method does not change the original object, but returns a new BigDecimal instance.

So, how do we optimize?

A: Catch the return value with a variable.

BigDecimal sum = new BigDecimal("0");
for (int i = 0; i < 5; i++) {
    sum = (new BigDecimal("1"));
}
(sum); 

The printout is: 5

The BigDecimal operation needs to catch the new instance after the operation.

6 Ignoring performance issues

BigDecimal is very precise, but also very slow.

Using BigDecimal for a large number of calculations can slow down performance, such as calculating interest:

BigDecimal principal = new BigDecimal("10000");
BigDecimal rate = new BigDecimal("0.05");
BigDecimal interest = (rate);

Messing with it a million times in one loop pulls performance right down.

So how do we optimize for this situation?

A: Use whole numbers when you can (e.g. cents instead of dollars).

For batch calculations, double is used and the result is finally converted to BigDecimal.

double principal = 10000;
double rate = 0.05;
BigDecimal interest = (principal * rate);
(interest); 

Printed result: 500.00

Participate in large quantities of calculation, two BigDecimal object direct calculation will be slower, as little as possible, don't let go where you can optimize.

put at the end

BigDecimal is a very powerful numeric tool, but it's also a "detail freak".

You can only really enjoy the benefits it brings if you use it right, otherwise you're just asking for trouble.

I hope this article helps you not to step in the hole again.

If there is any other usage confusion, feel free to leave a comment to discuss and we'll grow together!

One final note (ask for attention, don't patronize me)

If this article is helpful to you, or inspired, help pay attention to my eponymous public number: Su San said technology, your support is my biggest motivation to keep writing.

Ask for a one-click trifecta: like, retweet, and watch at.

Concerned about the public number: [Su San said technology], in the public number reply: into the big factory, you can get free access to my recent organization of 100,000 words of the interview dictionary, a lot of partners rely on this dictionary to get a number of big factory offers.