|
|
Posted on 4/7/2015 2:53:05 PM
|
|
|

Operation classes for large numbers are provided in java, namely the java.math.BinInteger class and the java.math.BigDecimal class. These two classes are used for high-precision computing, with the BigInteger class being the processing class for large integers and the BigDecimal class being the processing class for large and small numbers. Below we introduce the BigDecimal class: The implementation of BigDecimal takes advantage of BigInteger, except that BigDecimal adds the concept of decimals. General float and double type data can only be used for scientific calculations or engineering calculations, because in commercial computing, the required numerical accuracy is relatively high, so the java.math.BigDecimal class is used, which supports any precision of fixed points, and can be used to accurately calculate currency values. Below we will briefly introduce its usage with examples
java.math.BigDecimal
Today, I wrote a program about binary and decimal conversion with reference to the textbook, and the program algorithm is not difficult, but after writing, I found that whether it is 2 to 10 or 10 to 2, it is not a good conversion for numbers greater than 2.1 billion, that is, more than the integer range. will become 0. Reference books have found that using BigInteger solves this problem. So I looked up the JDK, and then tested it several times and finally wrote it successfully! The usage experience is as follows:
1. BigInteger belongs to java.math.BigInteger, so import this class before each use. Occasionally, I forgot to import at the beginning, so the prompt cannot be found in the constant prompt.
2. There are many construction methods, but now they are occasionally used: BigInteger(String val) Convert the decimal string representation of BigInteger to BigInteger. BigInteger(String val, int radix) Converts the string representation of the BigInteger for the specified cardinality to the BigInteger. To convert 2 of int type to BigInteger type, write BigInteger two=new BigInteger("2"); Note 2 double quotation marks cannot be omitted
3. The BigInteger class simulates all int-type mathematical operations, such as add()=="+", divide()=="-", etc., but note that its content cannot be directly used for mathematical operations when performing mathematical operations, and must use its internal methods. And its operand must also be of type BigInteger. For example: two.add(2) is an incorrect operation because 2 does not become a BigInteger type.
4. When you want to output the calculation results, you should use the .toString method to convert it into a decimal string, as detailed as follows: String toString() Returns the decimal string representation of this BigInteger. Output method: System.out.print(two.toString());
5. Explain the three functions used. BigInteger remainder(BigInteger val) Returns a BigInteger with a value of (this % val). BigInteger negate() BigInteger returns a value of (-this). int compareTo(BigInteger val) Compare this BigInteger to the specified BigInteger. remainderis used to find the remainder. negate turns the operand into the opposite. Compare is explained in detail as follows: compareTo
public int compareTo(BigInteger val)
Compare this BigInteger to the specified BigInteger. This method is preferred for each of the six Boolean comparison operators (<, ==, >, >=, !=, <=). The suggested statement to perform these comparisons is: (x.compareTo(y) <op> 0), where is <op> one of the six comparison operators.
Specifier: interface<BigInteger> Comparable
Parameters: val - The BigInteger that compares this BigInteger to it. Back:
Title Implementing Precise Calculations of Floating Point Numbers in Java AYellow (Original) Modification Keywords Java floating-point number precise calculation
Question asked: What would we see if we compiled and ran the following program? public class Test{ public static void main(String args[]){ 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 read that right! The result is, indeed 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Simple float and double types in Java cannot be operated. This problem is not only found in Java, but also in many other programming languages. In most cases, the calculations are accurate, but you can try a few more times (you can do a loop) to try errors like the one above. Now I finally understand why there is a BCD code. This problem is quite serious, if you have 9.9999999999999999 yuan, your computer will not think that you can buy 10 yuan of goods. Some programming languages provide specialized currency types to handle this situation, but Java does not. Now let's see how to fix this.
Rounding Our first reaction is to do rounding. The round method in the Math class cannot be set to keep a few decimal places, we can only do this (keep two places): public double round(double value){ return Math.round(value*100)/100.0; }
Unfortunately, the above code doesn't work, passing in 4.015 to this method will return 4.01 instead of 4.02, as we saw above 4.015*100=401.49999999999994 Therefore, if we want to do accurate rounding, we cannot use simple types to do any operations java.text.DecimalFormat doesn't solve this problem either: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); The output is 4.02
BigDecimal This principle is also mentioned in the book "Effective Java", float and double can only be used for scientific or engineering calculations, and in business computing we need to use java.math.BigDecimal. There are 4 ways to build BigDecimal, we don't care about the two that are made with BigInteger, so there are two more, which are: BigDecimal(double val) Translates a double into a BigDecimal. BigDecimal(String val) Translates the String repre sentation of a BigDecimal into a BigDecimal.
The API is briefly described and is usually easier to use. We may use it without even thinking about it, what will be the problem? When something went wrong, I found out that there was such a paragraph in the detailed description of which of the above methods was sufficient: Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot 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 accurately, we have to use String to create BigDecimal! The example in the book Effective Java uses String to create BigDecimal, but the book does not emphasize this, which may be a small mistake.
Solution Now that we have solved this problem, the principle is to use BigDecimal and make sure to use String. But imagine if we want to do an addition operation, we need to first convert two floating-point numbers to String, then create a BigDecimal, call the add method on one of them, pass the other as an argument, and then convert the result of the operation (BigDecimal) to a floating-point number. Can you endure such a tedious process? Below we provide a tool class Arith to simplify the operation. It offers the following static methods, including addition, subtraction, multiplication and division, 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.java:
import java.math.BigDecimal; /** * Since Java's simple types cannot accurately perform floating-point operations, this tool class provides fines * Exact floating-point operations, including addition, subtraction, multiplication, division, and rounding. */
public class Arith{
Default division operation accuracy private static final int DEF_DIV_SCALE = 10;
This class cannot be instantiated private Arith(){ }
/** * Provides precise addition operations. * @param v1 is added * @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 is subtracted * @param v2 minus * @return The difference between the 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 operations. * @param v1 is multiplied * @param v2 multiplier * @return The product of the 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 inexhaustible division occurs * 10 decimal places and the following digits are rounded. * @param v1 is divised * @param v2 divisor * @return The quotient of the two parameters */
public static double div(double v1,double v2){ return div(v1,v2,DEF_DIV_SCALE); }
/** * Provides (relatively) accurate division operations. When an inexhaustible situation occurs, it is indicated by the scale parameter * Determine the accuracy, and the numbers after it will be rounded. * @param v1 is divised * @param v2 divisor * @param scale indicates that it needs to be accurate to a few decimal places. * @return The quotient of the 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 decimal rounding. * @param v requires rounding numbers * @param scale is reserved after the decimal point * @return Rounded results */
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(); } }; |
Previous:It is best not to set a string with meaning as a primary keyNext:JDK, JRE, JVM differences and connections
|