Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the pits encountered by BigDecimal?

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "what are the pits encountered by BigDecimal". In daily operation, I believe that many people have doubts about the pits encountered by BigDecimal. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful for you to answer the doubts about "what pits BigDecimal encountered". Next, please follow the editor to study!

Avoid using Double for operations

Using Double to calculate, we think that the arithmetic operation and computer calculation are not exactly all the time, this is because the computer stores values in binary, the decimal values we enter will be converted into binary to calculate, decimal to binary and then converted to decimal is not the original decimal system, it is no longer the same teenager. For example: the conversion from decimal 0.1 to binary is 0.0 0011 0011 0011. (countless 0011), and then converted to decimal system is 0.1000000000000000055511151231, see, I didn't lie to you.

It is inevitable that the computer cannot accurately express floating-point numbers, which is the reason why the accuracy of floating-point numbers is lost after calculation.

System.out.println (0.1 to 0.2); System.out.println (1.0 to 0.8); System.out.println (4.015 to 100); System.out.println (123.3 to 100)

Through a simple example, we find that the loss of accuracy is not great, but this does not mean that we can use it, especially in e-commerce systems, where millions of units are reduced every day, and even if each order is calculated by a penny less, it is not a small amount. So, this is not a small thing, and then many people say, the amount calculation, ah, you use BigDecimal, ah, this is not a problem. But will it be all right with BigDecimal? When asked this sentence, it shows that there must be something wrong with it.

BigDecimal, what kind of pits have you encountered?

Let's take a look at the result by calculating the operation in the above example through a simple example:

System.out.println (new BigDecimal (0. 1). Add (new BigDecimal (0. 2)); System.out.println (new BigDecimal (1. 0). Subtract (new BigDecimal (0. 8)); System.out.println (new BigDecimal (4.015). Multiply (new BigDecimal (100)); System.out.println (new BigDecimal (123.3).

We find that the calculation results are still not accurate after using BigDecimal, so here is the first pit of BigDecimal:

When BigDecimal is used to represent and calculate floating point numbers, the BigDecimal is initialized using the constructor of String.

Let's take a look at the results with a little improvement:

System.out.println (new BigDecimal ("0.1") .add (new BigDecimal (" 0.2")); System.out.println (new BigDecimal ("1.0") .subtract (new BigDecimal (" 0.08"); System.out.println (new BigDecimal ("4.015") .multiply (new BigDecimal ("4.015")); System.out.println (new BigDecimal ("123.3") .subtract (new BigDecimal ("123.3")

So the next question is, will everything be all right with BigDecimal? It's not!

Next, let's take a look at the source code of BigDecimal. There is one thing to pay attention to. First, look at the figure:

Notice that these two attributes, scale represents a few digits to the right of the decimal point, and precision represents precision, which is what we often call the effective length.

We already know that BigDecimal must pass in a string type numeric value, so what if we are now a Double type numeric value? Let's take a look at this through a simple test:

Private static void testScale () {BigDecimal bigDecimal1 = new BigDecimal (Double.toString (100d); BigDecimal bigDecimal2 = new BigDecimal (String.valueOf (100d)); BigDecimal bigDecimal3 = BigDecimal.valueOf (100d); BigDecimal bigDecimal4 = new BigDecimal (100d); BigDecimal bigDecimal5 = new BigDecimal (String.valueOf (100d); print (bigDecimal1); print (bigDecimal2); print (bigDecimal3); print (bigDecimal4); print (bigDecimal5) } private static void print (BigDecimal bigDecimal) {System.out.println (String.format ("scale% s precision s result% s", bigDecimal.scale (), bigDecimal.precision (), bigDecimal.multiply (new BigDecimal ("1.001");}

Run, we found that after the first three methods are converted from double to BigDecimal, the scale of the BigDecimal is 1, the scale of the toString method of the latter two methods is 3, and the scale of the latter two methods is 3. After multiplying with 1.001, we find that scale is the result of the addition of the scale of two numbers.

When dealing with floating-point strings, we should explicitly specify the number of decimal places and rounding through formatting expressions or formatting tools.

How to choose the rounding and formatting of floating point numbers?

Let's first take a look at the result of formatted rounding using String.format. We know that there are two kinds of floating-point numbers, double and float. Let's use these two as examples:

Double num1 = 3.35; float num2 = 3.35f; System.out.println (String.format ("% .1f", num1)); System.out.println (String.format ("% .1f", num2))

The result seems to be different from our expectations, but in fact, this problem is also easy to explain. The accuracy of double and float is different. 3.35 of double is equivalent to 3.350000000000888178419700125233890533447265625, while 3.35 of float is equivalent to 3.3499999046325689375 string. Format is rounded again, so the accuracy problem and rounding method lead to different results from our expectations.

The HALF_UP rounding method is used by default in the Formatter class. If we need to use other rounding methods to format it, we can set it manually.

At this point, we know that there are a lot of holes in formatting this path through String.format, so "string formatting for floating-point numbers still has to be done using BigDecimal."

Come on, go to the code and test if that's the case:

BigDecimal num1 = new BigDecimal ("3.35"); / / 1 place after the decimal point, rounding down BigDecimal num2 = num1.setScale (1, BigDecimal.ROUND_DOWN); System.out.println (num2); / / 1 place after the decimal point, rounding BigDecimal num3 = num1.setScale (1, BigDecimal.ROUND_HALF_UP); System.out.println (num3); input result: 3.3.4

The results obtained this time are in line with our expectations.

BigDecimal cannot be compared using the equals method?

We all know that wrapper class comparisons use equals instead of = =, so does this also apply in Bigdecimal? Data speaking, a simple test to illustrate:

System.out.println (new BigDecimal ("1") .equals (new BigDecimal ("1")) result: false

According to our understanding, 1 and 1 are equal and should be equal, but the equals of Bigdecimal compares not only value, but also scale. We said earlier that scale is the number of places after the decimal point, obviously the number of decimal places of the two values is not the same, so the result is false.

In practice, we often only want to compare the value of two BigDecimal. Note here that you need to use the compareTo method:

System.out.println (new BigDecimal ("1"). Compareto (new BigDecimal ("1")) result: true here, the study of "what are the pitfalls encountered by BigDecimal" is over, hoping to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report