BigDecimal performs exact decimal Calculation

Source: Internet
Author: User

To consider this situation, first look at the Code:


Public static void main (String [] args ){

System. out. println (0.4 + 0.8); // = 1.2?
System. out. println (2-1.1); // = 0.9?
System. out. println (0.2*3); // = 0.6?
System. out. println (1.2/3); // = 0.4?

}

Maybe you would naively think that the first row prints 1.2, the second row prints 0.9, the third row prints 0.6, and the fourth row prints 0.4, it is a matter of course because the output results of the mathematical inertia logic for many years are consistent with the expected ones!

However, after the program is run, the output results differ greatly from the expected ones. Let's look at the results printed in the background:


1.2000000000000002
0.8999999999999999
0.6000000000000001
0.39999999999999997
 

Is it depressing to see such a result? Of course, I picked these data on purpose. Not all operations involving floating point numbers will calculate such unexpected results, but one thing that is clear is,

When operations involve floating-point operations, we must guard against such operations.

In the code above, addition, subtraction, multiplication, division, all of them belong to double-level operations. Why do we print the output results? The reason is that not all floating point numbers can be accurately expressed as one

Double Type value. Some floating point values cannot be accurately expressed as double type values, so they are expressed as double type values closest to them. So unfortunately, 0.4 + 0.8 = 1.2 .......

How can we solve this problem? A BigDecimal class is provided in java to perform precise decimal calculations. The BigDecimal class provides the following operations: arithmetic, scale operations, rounding, comparison, hash algorithms, and format conversion.

The BigDecimal class provides the following methods:

Addition: add

Subtraction: subtract

Multiplication: multiply

Division: divide

...... ......

For more methods provided by the BigDecimal class, see the API. The following uses the BigDecimal class to rewrite the above Code:


Public static void main (String [] args ){

System. out. println (new BigDecimal (0.4). add (new BigDecimal (0.8); // = 1.2?
System. out. println (new BigDecimal (2). subtract (new BigDecimal (1.1); // = 0.9?
System. out. println (new BigDecimal (0.2). multiply (new BigDecimal (3); // = 0.6?
System. out. println (new BigDecimal (1.2). divide (new BigDecimal (3); // = 0.4?

}

Maybe you are checking the BigDecimal-like API. The API has a large string of text descriptions for the BigDecimal class. Maybe you haven't finished reading it yet, but you can be sure that, bigDecimal class can accurately ensure precise decimal execution,

Do I forget to remove the comments of the above Code? No. If so, it would be a big fault. Let's take a look at the output result of the background printing:


1.20000000000000006661338147750939242541790008544921875
0.899999999999999911182158029987476766109466552734375
0.600000000000000033306690738754696212708950042724609375
Exception in thread "main" java. lang. ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
At java. math. BigDecimal. divide (BigDecimal. java: 1603)
At example. BigDecimalApp. main (BigDecimalApp. java: 20)

If you are playing this game, you will see that the results are even more disgusting. This is not enough, and an exception is thrown. Why? Don't worry. Let's take a look at what the API says:

"
Public BigDecimal (double val)

Convert double to BigDecimal. The latter is the exact decimal representation of the binary floating point value of double. The returned BigDecimal scale is the minimum value that makes (10 scale x val) an integer.

Note:


1. The results of this constructor are unpredictable. Some people may think that the BigDecimal created by writing new BigDecimal (0.1) in Java is exactly equal to 0.1 (the non-standard degree value 1, its scale is 1), but it is actually equal

0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be accurately expressed as double (or in this case, it cannot be expressed as any binary decimal with a limited length)

In this way, the value passed into the constructor is not exactly equal to 0.1 (although it is equal to this value on the surface ).

2. On the other hand, the String constructor is completely predictable: writing new BigDecimal ("0.1") will create a BigDecimal, Which is exactly equal to the expected 0.1. Therefore, we recommend that you use the String constructor first.

3. when double must be used as the source of BigDecimal, please note that this constructor provides an accurate conversion; it does not provide the same result as the following operation: Use Double first. toString (double) method,

Then use the BigDecimal (String) constructor to convert double to String. To obtain this result, use the static valueOf (double) method.


Parameters:
Val-the double value to be converted to BigDecimal.

Throw:
NumberFormatException-if val is infinite or NaN.


"

The above text is taken from the API. The API explains it clearly. I will not talk about it here. We recommend that you use the String constructor for the API. Let's just give it a try:


Public static void main (String [] args ){

System. out. println (new BigDecimal ("0.4"). add (new BigDecimal ("0.8"); // = 1.2 √
System. out. println (new BigDecimal ("2"). subtract (new BigDecimal ("1.1"); // = 0.9 √
System. out. println (new BigDecimal ("0.2"). multiply (new BigDecimal ("3"); // = 0.6 √
System. out. println (new BigDecimal ("1.2"). divide (new BigDecimal ("3"); // = 0.4 √

}

Output result in the background:


1.2
0.9
0.6
0.4
 

OK, now the child is no longer a child, so you must never use the BigDecimal (double) constructor to create a BigDecimal object, because the constructor creates an Instance Object Based on the exact value of its parameters,

The results of this constructor are still unpredictable. You can use the BigDecimal (String) constructor to create a BigDecimal instance.

The add, subtract, multiply, and divide methods in the BigDecimal class are mentioned above. In the API, you can see that these methods have their own overload methods, such:

Add (BigDecimal augend, MathContext mc )......

What does the second parameter mc mean? Let's take a look at a piece of code:


Public static void main (String [] args ){

// Keep two valid numbers for the calculation result
System. out. println (new BigDecimal (Math. PI + ""). add (new BigDecimal ("0.89842"), new MathContext (2); // output 4.0

} Www.2cto.com

The second parameter mc is used to retain the number of valid digits of the calculation result. The reload usage of the other three methods is the same, and it is not listed here.


 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.