使用BigDecimal进行精确运算

一 . 简介:

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double能够处理16位有效数。在实际应用中,须要对更大或者更小的数进行运算和处理。float和double只能用来作科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所建立的是对象,咱们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来建立对象,特别是带有参数的对象。html

示例:

public class Test_1 {
     public static void main(String[] args) {
         System.out.println(0.06+0.01);
         System.out.println(1.0-0.42);
         System.out.println(4.015*100);
         System.out.println(303.1/1000);
     }
     
 }

运行结果:java

0.06999999999999999

0.5800000000000001

401.49999999999994

0.30310000000000004

你认为你看错了,但结果倒是是这样的。问题在哪里呢?缘由在于咱们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。咱们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法通常都会失去必定的精确度,有些浮点数运算也会产生必定的偏差。如:2.4的二进制表示并不是就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值其实是由一个特定的数学公式计算获得的git

构造方法摘要
BigDecimal(BigInteger val) 
          将 BigInteger 转换为 BigDecimal。
BigDecimal(BigInteger unscaledVal, int scale) 
          将 BigInteger 非标度值和 int 标度转换为 BigDecimal。
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) 
          将 BigInteger 非标度值和 int 标度转换为 BigDecimal(根据上下文设置进行舍入)。
BigDecimal(BigInteger val, MathContext mc) 
          将 BigInteger 转换为 BigDecimal(根据上下文设置进行舍入)。
BigDecimal(char[] in) 
          将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列。
BigDecimal(char[] in, int offset, int len) 
          将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列,同时容许指定子数组。
BigDecimal(char[] in, int offset, int len, MathContext mc) 
          将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列,同时容许指定子数组,并根据上下文设置进行舍入。
BigDecimal(char[] in, MathContext mc) 
          将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列(根据上下文设置进行舍入)。
BigDecimal(double val) 
          将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。
BigDecimal(double val, MathContext mc) 
          将 double 转换为 BigDecimal(根据上下文设置进行舍入)。
BigDecimal(int val) 
          将 int 转换为 BigDecimal。
BigDecimal(int val, MathContext mc) 
          将 int 转换为 BigDecimal(根据上下文设置进行舍入)。
BigDecimal(long val) 
          将 long 转换为 BigDecimal。
BigDecimal(long val, MathContext mc) 
          将 long 转换为 BigDecimal(根据上下文设置进行舍入)。
BigDecimal(String val) 
          将 BigDecimal 的字符串表示形式转换为 BigDecimal。
BigDecimal(String val, MathContext mc) 
          将 BigDecimal 的字符串表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符串(按照上下文设置进行舍入)。

 

二. 使用:

1.在使用BigDecimal类来进行计算的时候,主要分为如下步骤:api

  • 用float或者double变量构建BigDecimal对象:

( 1 ). BigDecimal BigDecimal(double d); //不容许使用,此构造方法的结果有必定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所建立的 BigDecimal 正好等于 0.1(非标度值 1,其标度为 1),可是它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是由于 0.1 没法准确地表示为 double(或者说对于该状况,不能表示为任何有限长度的二进制小数)。这样,传入 到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。
( 2 ). BigDecimal BigDecimal(String s); //经常使用,推荐使用
( 3 ). static BigDecimal valueOf(double d); //经常使用,推荐使用数组

  • 经过调用BigDecimal的加,减,乘,除等相应的方法进行算术运算:
BigDecimal add(BigDecimal)        //与另外一个BigDecimal对象相加,而后返回结果对象 
BigDecimal subtract(BigDecimal)   //与另外一个BigDecimal对象相减,而后返回这个对象 
BigDecimal multiply(BigDecimal)   //与另外一个BigDecimal对象相乘,而后返回这个对象 
BigDecimal divide(BigDecimal)     //与另外一个BigDecimal对象相除,而后返回这个对象
  • 把BigDecimal对象转换成float,double,int等类型:
String toString()                 //将BigDecimal对象的数值转换成字符串 
double doubleValue()              //将BigDecimal对象中的值以双精度数返回 
float floatValue()                //将BigDecimal对象中的值以单精度数返回 
long longValue()                  //将BigDecimal对象中的值以长整数返回 
int intValue()                    //将BigDecimal对象中的值以整数返回

 

2.其余经常使用方法:ide

/** 
 * 求余数 
 * 返回值为 (this % divisor) 的 BigDecimal 
 */  
BigDecimal remainder(BigDecimal divisor);  
  
/** 
 * 求相反数 
 * 返回值是 (-this) 的 BigDecimal 
 */  
BigDecimal negate();  
  
/** 
 * 将此 BigDecimal 与指定的 BigDecimal 比较 
 * 根据此方法,值相等但具备不一样标度的两个 BigDecimal 对象(如,2.0 和 2.00)被认为是相等的; 
 * 相对六个 boolean 比较运算符 (<, ==, >, >=, !=, <=) 中每个运算符的各个方法,优先提供此方法; 
 * 建议使用如下语句执行上述比较:(x.compareTo(y) <op> 0), 其中 <op> 是六个比较运算符之一; 
 * 
 * 指定者:接口 Comparable<BigDecimal> 中的 compareTo 
 * 返回:当此 BigDecimal 在数字上小于、等于或大于 val 时,返回 -一、0 或 1 
 */  
int compareTo(BigDecimal val);

 

三. 与NumberFormat配合进行数据格式化

因为java.text.NumberFormat类的format()方法可使用BigDecimal对象做为其参数,能够利用BigDecimal对超出16位有效数字的货币值,百分值,以及通常数值进行格式化控制。若是对NumberFormat不熟悉请点击这里this

public static void main(String[] args) {
    NumberFormat currency = NumberFormat.getCurrencyInstance(); //创建货币格式化引用 
    NumberFormat percent = NumberFormat.getPercentInstance();  //创建百分比格式化引用 
    percent.setMaximumFractionDigits(3); //百分比小数点最多3位 
    
    BigDecimal loanAmount = new BigDecimal("15000.48"); //贷款金额
    BigDecimal interestRate = new BigDecimal("0.008"); //利率   
    BigDecimal interest = loanAmount.multiply(interestRate); //相乘

    System.out.println("贷款金额:\t" + currency.format(loanAmount)); 
    System.out.println("利率:\t" + percent.format(interestRate)); 
    System.out.println("利息:\t" + currency.format(interest)); 
}

运行结果:spa

贷款金额:    ¥15,000.48
利率:    0.8%
利息:    ¥120.00
相关文章
相关标签/搜索