statement of problem:
What will I see if we can compile this program? Public class test {public static void main (string args []) {system.out.println (0.05 0.01); system.out.println (1.0-0.02); system.out.println (4.015 * 100); system. Out.println (123.3 / 100);}}; you have not mistisred! The result is really simple floating point types float and double in 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999 Java can not be operated. Not only Java, there is such a problem in many other programming languages. In most cases, the result of the calculation is accurate, but it can be tried several times (can be a loop) to try the above errors. Now I finally understand why there is a BCD code. This problem is quite serious, if you have 9.99999999999 yuan, your computer will not think you can purchase 10 yuan. This situation is provided in a programming language to handle this situation, but Java is not. Let us now look at how to solve this problem.
rounding
Our first reaction is to do four. The Round method in the MATH class cannot be set to keep several decimal numbers, we can only like this (reserved two): public double round (double value) {return math.round (value * 100) /100.0;} is very unfortunate, top The code does not work normally, introduced to this method into 4.015 it will return 4.01 instead of 4.02, such as the 4.015 * 100 = 401.4999999999999, therefore, if we have to do accurate round, you can't use the simple type to do any operation Java .Text.DecimalFormat also does not solve this problem: System.out.println (new java.text.decimalformat ("0.00"). Format (4.025)); output is 4.02
BigDecimal mentioned this principle in "Effective Java", float and double can only be used to make scientific calculations or project calculations, we have to use java.math.bigDecimal in business calculations. BigDecimal has four enough methods, we don't care two of Biginteger, then there are two, they are: BigDecimal (Double Val) A Double Into A BigDecimal. BigDecimal (String Val) TRANSLATES THE String Repe Sentation of a BigDecimal INTO A BIGDECIMAL. The above API is quite clear, and in general, the one of the above is convenient. We may want to use it, what is the problem? When you have a problem, you will find this detailed description of the above method: NOTE: The Results of this constructor can be becomewhat unpredictable. One might assume tria new bigdecimal (.1) IS exactly equal to .1 , but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 can not be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances nonwithstanding The (String) constructor, on the other hand, is perfectly predictable:. new BigDecimal ( ". 1") is exactly equal to .1, as one would expect Therefore. , IT IS generally recommended That the (String) constructor be used in preference to this one. It turns out that if we need to calculate, you have to use String to make BigDecimal! The example in the "Effective Java" book is to make BigDecimal with String, but the book is not emphasized, this may be a small mistake.
solution
Now we can solve this problem, the principle is to use BigDecimal and must use String to make it. But imagine it, if we have to do an additional operation, you need to turn the two floating point numbers to string, then make BigDecimal, one of them, to send another as a parameter, then put the calculation result ( BigDecimal is converted to floating point. Can you endure such a cumbersome process? Below we provide a tool class Arith to simplify operation. It provides the following static methods, including addition and subtraction and rounding and rounding: Public Static Double Add (Double V1, Double V2) Public Static Double Sub (Double V1, Double V2) Public Static Double MUL (Double V1, Double V2) Public Static Double Div (Double V1, Double V2) Public Static Double Div (Double V1, Double V2, INT Scale) Public Static Double Round (Double V, INT Scale) Appendix
Source file arith.com .java:
Import java.math.bigdecimal;
/ ** * Since Java's simple type is not accurate to calculate floating point numbers, this tool class provides the Floating point count operation, including addition and subtraction and division and rounding. * / Public class arith {
// Default division operation accuracy private static final int def_div_scale = 10;
// This class cannot instantiate private arch () {}
/ ** * Provide an accurate addition operation. * @Param V1 Plus * @Param V2 plus * @return two parameters and * / 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 ();
/ ** * Provide an accurate subtraction operation. * @Param V1 is reduced * @Param V2 reduction * @return two parameters of difference * / 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 ();
/ ** * Provide precise multiplication. * @Param V1 Multiply * @Param V2 Multiply * @return 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, accurate when there is an endless case * After the decimal point, the number will be rounded in the future. * @Param V1 Demand * @Param V2 divisor * @Return two parameters * / public static double div (double V1, double v2) {Return Div (V1, V2, DEF_DIV_SCALE);}
/ ** * Provides (relatively) precise division operations. When an endless case occurs, the Scale parameter refers to * fixed precision, and the number will be rounded. * @Param V1 is divisted * @Param V2 divisor * @Param scale means that several digits are required to be accurate to the decimal point. * @return two parameters * / public static double div (Double V1, Double V2, int Scale) {if (scale <0) {throw new illegalgumentException ("The Scale Must Be a Positive Integer OR Zero);} BigDecimal B1 = New BigDecimal (V1)); BigDecimal B2 = New BigDecimal (Double.Tostring (V2)); Return B1.DIVIDE (B2, Scale, BigDecimal.Round_Half_up) .doubleValue ();
/ ** * Provide exact decimal round-stricken processing. * @Param V Requesquees a number of numbers * @Param Scale reserved several * @return four-year-old result * / public static double round (double v, int scale) {if (scale <0) {throw new IllegaArGumentexception (" 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 ();}}; transferred from: http://www.dalianit.com/
http://www.dalianit.com/edu/{78.85.66.123.79.69.74.62}.html