文档章节

使用BigDecimal进行精确运算

f
 fqian
发布于 2017/03/28 16:57
字数 1591
阅读 64
收藏 0

一 . 简介:

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

示例:

 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);
     }
     
 }

运行结果:

0.06999999999999999

0.5800000000000001

401.49999999999994

0.30310000000000004

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

构造方法摘要
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类来进行计算的时候,主要分为以下步骤:

  • 用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.其他常用方法:

/** 
 * 求余数 
 * 返回值为 (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 时,返回 -1、0 或 1 
 */  
int compareTo(BigDecimal val); 

 

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

由于java.text.NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。如果对NumberFormat不熟悉请点击这里

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)); 
}

运行结果:

贷款金额:    ¥15,000.48
利率:    0.8%
利息:    ¥120.00

 

© 著作权归作者所有

f
粉丝 1
博文 28
码字总数 40643
作品 0
宁波
私信 提问

暂无文章

axios 使用步骤很简单,首先在前端项目中,引入 axios:

  前端网络访问,主流方案就是 Ajax,Vue 也不例外,在 Vue2.0 之前,网络访问较多的采用 vue-resources,Vue2.0 之后,官方不再建议使用 vue-resources ,这个项目本身也停止维护,目前建...

SEOwhywhy
33分钟前
4
0
c++ 创建对象的三种方法

c++有三种方法创建对象 结合代码来看 1 #include <iostream> 2 using namespace std; 3 class Test { 4 5 private: 6 public: 7 add() 8 { 9 ......

天王盖地虎626
47分钟前
1
0
ant 中的fileset include等拷贝

拷贝一个目录到指定目录下 例:<copy todir="${basedir}/new"> <fileset dir="${basedir}/old"> <include name="appgen" /> <include name="appgen/" /> <include name=appgen/**" /> <incl......

shzwork
53分钟前
2
0
react-jianshu项目的创建

创建项目 1、github上创建仓库react-jianshu 2、将项目克隆到本地git clone git@github.com:startjcu/react-jianshu.git 3、在当前目录(项目目录的上级目录)下执行create-react-app react-...

星闪海洋
今天
2
0
OSChina 周二乱弹 —— 小哥哥,你可以教我写代码吗

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @nnnm: 生活大爆炸,结束了,这部陪伴了漫长时间的情景喜剧,最终是以诺贝尔奖和大团圆收尾的。虽然,不算精彩,但也是温馨。而少年谢尔顿的...

小小编辑
今天
945
14

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部