The problem of inaccurate operations on floating-point numbers

Source: Internet
Author: User

Http://edu.eoe.cn/online classroom

Yesterday I saw a post about a few simple floating-point operations, and the computer would be wrong.
Let me introduce it to you :'
RunCode:

 
System. Out. println (0.05 + 0.01); System. Out. println (1.0-0.42); System. Out. println (4.015*100); System. Out. println (123.3/100 );

You can create a new project by yourself. The result is as follows:

 
0.06000000000000000000050.5800000000000001401.499999999999941.200009999999999999

This is amazing. 0.05 + 0.01 is obviously 0.06, but why is it 0.060000000000000005?
Is the calculator too mentally retarded? Is it true that the computer is unreliable?

Of course not.This is mainly because the simple type in Java is not suitable for exact floating point calculation. Not only Java, but other languages also have the same problem.
Although the CPU now supports floating-point operations, when the CPU is processing, it first converts a floating-point number (float, double) into an integer and then binary, and then performs operations, there are different methods for obtaining the remainder.
After the computation is completed, it is necessary to convert multiple binary values to the upper floating point. This leads to a simple and obvious error.

Therefore, float and double are generally used for scientific or engineering computing. BCD code or Java. Math. bigdecimal is usually used in areas with high precision requirements (such as commercial.

BSD code (Binary-coded decimal)BCD or binary decimal code, also known as binary decimal number. It is a binary digital encoding format that uses binary-encoded decimal code.
If you are interested in this, you can take a deeper look. Today we are mainly talking about the bigdecimal class. This is because when we are working on projects, especially for commercial projects, we cannot create any BSD code. We can directly use the bigdecimal class to fulfill our needs.

Bigdecimal is an unchangeable, any-precision, and signed decimal number provided by Java. If you want to learn more about bigdecimal, you can view the JDK documentation on your own.

Bigdecimal provides a series of constructors for converting double and string objects to bigdecimal objects.

 
Bigdecimal (DoubleVal)DoubleConvert to bigdecimal, which isDoubleIn decimal format. Bigdecimal (string Val) converts the string representation of bigdecimal to bigdecimal.

Traditionally, when we use floating point numbers, we define the double and float data types directly, which is no problem in definition. However, if we call the bigdecimal (double Val) method directly for conversion, note the detailed descriptions of this structure in the JDK document:

Now you can go directly to Chinese. If the English is good, you can view the original version:

Note:
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 to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be accurately expressed as a 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 ).

Bigdecimal (double Val) is unpredictable, so we recommend using bigdecimal (string Val ).
The string constructor is predictable. The new bigdecimal (". 1") is exactly equal to. 1 as expected.

Next, let's modify 0.05 + 0.01 again:

 
Bigdecimal bd1 =NewBigdecimal (double. tostring (0.05)); Bigdecimal bd2=NewBigdecimal (double. tostring (0.01)); System. Out. println (bd1.add (bd2 ));

Let's take a look at the running results:

 
0.06

This is what we want, and we have completed a high-precision operation.

Note:
Now we know how to solve this problem. In principle, we recommend using the bigdecimal (string Val) constructor.
I suggest that in commercial applications, all floating-point operations involving money are defined as string and saved in the database as string. When you need to use this money for computation, we can convert string to bigdecimal to complete high-precision computation.

Imagine if we want to do an addition operation, we need to convert two floating point numbers into strings, and then convert them into bigdecimal. Call the add method on one of them and input another as the parameter, then convert the result of the operation (bigdecimal) to a floating point number. Can you endure this cumbersome process?

So, a good tool class is found on the internet, and simple operations are closed. For more information, see:

 /**  ** Because Java's simple types cannot accurately perform floating-point operations, this tool class provides ** exact floating-point operations, including addition, subtraction, multiplication, division, and rounding. **  */  Public   Class  Arith {  //  Default division accuracy     Private   Static   Final   Int Def_scale = 10 ;  //  This class cannot be instantiated.      Private  Arith (){}  /**  * Provides precise addition operations. *  @ Param  V1 increment *  @ Param  V2 addition *  @ Return The sum of the two parameters  */      Public   Static   Double Add ( Double V1, Double  V2) {bigdecimal B1 = New  Bigdecimal (double. tostring (V1); bigdecimal B2 = New  Bigdecimal (double. tostring (V2 ));  Return  B1.add (B2). doublevalue ();} /**  * Provides precise subtraction operations. *  @ Param  V1 subtrahend *  @ Param  V2 subtraction *  @ Return  Difference between two parameters  */      Public   Static   Double Sub ( Double V1, Double  V2) {bigdecimal B1 =New  Bigdecimal (double. tostring (V1); bigdecimal B2 = New  Bigdecimal (double. tostring (V2 ));  Return  B1.subtract (B2). doublevalue ();}  /**  * Provides precise multiplication. *  @ Param  V1 multiplier *  @ Param  V2 multiplier *  @ Return  Product of Two Parameters */      Public   Static   Double Mul ( Double V1, Double  V2) {bigdecimal B1 = New  Bigdecimal (double. tostring (V1); bigdecimal B2 = New  Bigdecimal (double. tostring (V2 ));  Return  B1.multiply (B2). doublevalue ();}  /** * Provides (relatively) accurate Division operations. When division is not complete, it is accurate to * 10 digits after the decimal point, and the digits after the decimal point are rounded down. *  @ Param  V1 divisor *  @ Param  V2 divisor *  @ Return  Vendors of Two Parameters  */      Public   Static   Double Div ( Double V1, Double  V2 ){  Return Div (V1, V2, def_scale );}  /**  * Provides (relatively) accurate Division operations. In case of division, the scale parameter determines * the precision, and the number is rounded down. *  @ Param  V1 divisor *  @ Param  V2 divisor *  @ Param  Scale indicates the number of digits after the decimal point. *  @ Return  Vendors of Two Parameters  */      Public   Static   Double Div ( Double V1, Double V2, Int  Scale ){  If (Scale <0 ){  Throw   New  Illegalargumentexception ( "The scale must be a positive integer or zero" );} Bigdecimal B1 = New  Bigdecimal (double. tostring (V1); bigdecimal B2 =New  Bigdecimal (double. tostring (V2 ));  Return  B1.divide (B2, scale, bigdecimal. round_half_up). doublevalue ();}  /**  * Provides precise rounding of decimal places. *  @ Param  V: Number rounded up *  @ Param  Number of decimal places after scale *  @ Return  Result After rounding  */      Public  Static   Double Round ( Double V, Int  Scale ){  If (Scale <0 ){  Throw   New  Illegalargumentexception ( "The scale must be a positive integer or zero" );} Bigdecimal B = New  Bigdecimal (double. tostring (v); bigdecimal one = New Bigdecimal ("1" );  Return  B. Divide (one, scale, bigdecimal. round_half_up). doublevalue ();}} 

Starting address: http://www.eoeandroid.com/thread-230579-1-1.html

Another address: http://krislq.com/150 Ga!

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.