Java BigDecimal conversion and division "traps"

Source: Internet
Author: User

In Java, double to BigDecimal is often used, and Division operations are often performed. However, you need to be especially careful with the following usage.

 

Java code
Package com. ccxe. number;

Import java. math. BigDecimal;
Import java. math. RoundingMode;

Public class Test {

Public static void main (String [] args ){

// Print 0.899999999999999911182158029987476766109466552734375
System. out. println (new BigDecimal (2.00). subtract (new BigDecimal (Double
. ToString (1.10 ))));
// Double to BigDecimal
System. out. println (new BigDecimal (Double. toString (2.00 ))
. Subtract (new BigDecimal (1.10 )));

// Print 0.90
System. out. println (new BigDecimal ("2.00"). subtract (new BigDecimal (
"1.10 ")));

// Exception java. lang. ArithmeticException: Non-terminating decimal expansion;
// System. out. println (new BigDecimal ("2.00 ")
//. Divide (new BigDecimal ("1.10 ")));
// Print 1.81818
System. out. println (new BigDecimal ("2.00"). divide (
New BigDecimal ("1.10"), 5, RoundingMode. HALF_EVEN ));

}

}

Package com. ccxe. number;

Import java. math. BigDecimal;
Import java. math. RoundingMode;

Public class Test {

Public static void main (String [] args ){

// Print 0.899999999999999911182158029987476766109466552734375
System. out. println (new BigDecimal (2.00). subtract (new BigDecimal (Double
. ToString (1.10 ))));
// Double to BigDecimal
System. out. println (new BigDecimal (Double. toString (2.00 ))
. Subtract (new BigDecimal (1.10 )));

// Print 0.90
System. out. println (new BigDecimal ("2.00"). subtract (new BigDecimal (
"1.10 ")));

// Exception java. lang. ArithmeticException: Non-terminating decimal expansion;
// System. out. println (new BigDecimal ("2.00 ")
//. Divide (new BigDecimal ("1.10 ")));
// Print 1.81818
System. out. println (new BigDecimal ("2.00"). divide (
New BigDecimal ("1.10"), 5, RoundingMode. HALF_EVEN ));

}

}
This phenomenon will be explained below.

 

Body:

 

The sample code in the introduction illustrates two problems:

 

1, 11th rows: The execution result is different from 18 rows;

Rows 2 and 22nd: exception thrown.

 

More importantly, these two problems are very concealed during encoding ~. =

 

First look at the 1st questions:

 

Once we see that the subtraction result is very long, we immediately think that 1.10 cannot be accurately expressed in binary format. Then I found the answer in the JDK API. The statement is as follows:

 

C code
Public BigDecimal (double val)

Convert double to BigDecimal. The latter is the exact decimal representation of the binary floating point value of double. Return
The scale of BigDecimal is to make (10 scale × val) the minimum value of an integer.

Note:
(1) the results of this constructor are unpredictable. Some people may think that writing new BigDecimal (0.1) in Java)
The created BigDecimal is exactly equal to 0.1 (the non-standard degree value is 1, and its scale is 1), but it is actually equal
0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be accurately displayed.
Double (or in this case, it cannot be expressed as any binary decimal with a limited length ). In this way
The value of the Creation method 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
BigDecimal, Which is exactly 0.1 of the expected value. Therefore, we recommend that you use the String constructor first.
(3) When double must be used as the source of BigDecimal, note that this constructor provides an accurate conversion;
It does not provide the same results as the following operations: first use the Double. toString (double) method, and then use
BigDecimal (String) constructor, which converts double to String. To obtain this result, use
Static valueOf (double) method.

Parameters:
Val-the double value to be converted to BigDecimal.
Throw:
NumberFormatException-if val is infinite or NaN.

Public BigDecimal (double val)

Convert double to BigDecimal. The latter is the exact decimal representation of the binary floating point value of double. Return
The scale of BigDecimal is to make (10 scale × val) the minimum value of an integer.

Note:
(1) the results of this constructor are unpredictable. Some people may think that writing new BigDecimal (0.1) in Java)
The created BigDecimal is exactly equal to 0.1 (the non-standard degree value is 1, and its scale is 1), but it is actually equal
0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be accurately displayed.
Double (or in this case, it cannot be expressed as any binary decimal with a limited length ). In this way
The value of the Creation method 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
BigDecimal, Which is exactly 0.1 of the expected value. Therefore, we recommend that you use the String constructor first.
(3) When double must be used as the source of BigDecimal, note that this constructor provides an accurate conversion;
It does not provide the same results as the following operations: first use the Double. toString (double) method, and then use
BigDecimal (String) constructor, which converts double to String. To obtain this result, use
Static valueOf (double) method.

Parameters:
Val-the double value to be converted to BigDecimal.
Throw:
NumberFormatException-if val is infinite or NaN.

 

From this, we can see that it is indeed a classic problem that 10 hexadecimal cannot be accurately expressed as 2 hexadecimal.

 

Let's look at the second question:

 

We can guess from the error message "Non-terminating decimal expansion;" (Non-terminating decimal expansion), and the operator cannot accurately express it. Check the jdk api and find the following statement:

 

C code
Public BigDecimal divide (BigDecimal divisor)
Returns a BigDecimal with the value (this/divisor). The preferred scale is (this. scale ()
-Divisor. scale (); If the exact business value cannot be expressed (because it has infinite decimal extensions ),
ArithmeticException is thrown.

Parameters:

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.