转载请注明源出处:http://www.cnblogs.com/lighten/p/6963836.html

1.前言

  编程人员都应该知道计算机计算浮点数是不精确的,结果是近似数值,当然具体值还是和计算机操作的实现有关。因此,如果对于计算结果不需要过于精准的时候,使用浮点数类型是没什么问题的,但是如果要求精确值的话(比如计算利息),就不能使用这种不精确的结果了,而要选择java提供的用于计算精确浮点数的类BigDecimal。本文基于JDK1.8介绍此类的一般用法和源码实现。

  BigDecimal类注解的第一段就介绍了一些基本信息:不可变的、任意精度的十进制数。一个BigDecimal由任意精度的非刻度值整数和32位整数的刻度组成。如果值大于等于0,标度就是小数点后的位数,如果值小于0,值就是:非标度值*10^(-标度值)。这样说不好理解,后面会说明白构成。

  注意:上述的不可变指的并不是这个类被final修饰,而是指BigDecimal每次计算都是产生了一个新的对象,这点要注意。

2.用例

     @Test
public void test() {
BigDecimal b = new BigDecimal(1.22);
System.out.println(b.unscaledValue());
System.out.println(b.scale());
System.out.println(b);
String a = "2199999999999999733546474089962430298328399658203125";
System.out.println(a.length());
}

  上述例子运行的结果是:

  由此可以看出以下几点:1.double类型是不精确的;2.上面所说的非刻度值就是指去掉了小数点的浮点数;3.刻度值指的就是小数点后面的位数了。

  正数的时候计算值是非刻度值+小数点位数构成,如12345 4就是1.2345,四位小数;负数的时候则是-12345*10^(-4)结果是-1.2345。

        @Test
public void testMathContext() {
BigDecimal add = new BigDecimal("1.17");
BigDecimal a = new BigDecimal("12.324", new MathContext(3, RoundingMode.UP));
BigDecimal b = new BigDecimal("12.324", new MathContext(2, RoundingMode.UP));
BigDecimal d = new BigDecimal("12.324", new MathContext(1, RoundingMode.UP));
BigDecimal c = new BigDecimal("12.324", new MathContext(0, RoundingMode.UP));
System.out.println(a);
System.out.println(a.add(add)); // a变成12.4
System.out.println(b.add(add)); // a变成14
System.out.println(d.add(add)); // a变成20
System.out.println(c.add(add)); }

  上面一个例子展示了MathContext的用法,补充介绍了具体含义,这里说下第一个参数的作用,可以看出是设置了MathContext的那个BigDecimal在运算之前发生了变化。

3.源码解读

  关键字段:

private final BigInteger intVal;    // 无刻度整数(无小数点)
private final int scale; // 刻度值
private transient int precision;  // 无小数点的整数的位数
private final transient long intCompact;  //intVal如果其值小于Long.MAX_VALUE就可以紧凑的存储在这个字段方便计算

  BigDecimal有很多种构造方法:

  实际上也就是相互调用,主要的也就几个实现:首先所有具有BigInteger参数的构造方法都十分简单,大部分都是简单的赋值罢了。最多就是计算了一下intCompact的值:

  上述就是就是一个压缩过程,如果不能压缩就存一个标志位。

  入参为char和String的构造函数,最终调的都是方法:public BigDecimal(char[] in, int offset, int len, MathContext mc)。其它的int、long、double也都比较简单,int类型的时候intValue的值是null。总而言之,所有的构造方法,经过一系列运算,最终是要得到上面所列的四个关键字段的值。这些计算基本是位运算。值得一提的是可以通过静态valueof()方法来创建BigDecimal,过程大同小异。

  BigDecimal的运算函数:

    add();    // 加

    subtract()  // 减

    multiply()  // 乘

    divide()   // 除

    reminder()  //取余

    pow()    // 幂次方

    abs()    // 绝对值

    negate()  // 相反值(-this)

  等等,这里就不一一介绍了。

4.补充

  之前构造函数中会看见MathContext这个参数,这里补充介绍一下相关内容。MathContext:制定BigDecimal运算操作的运算规则。其主要是通过两个属性来控制的:

    final int precision;  // 被用于计算的位数,0就是不限制位数

    final RoundingMode roundingMode;  // 运算时的舍入规则,有很多,可以看源码上的注释,有举例说明。

  默认使用的是无限制,ROUND_HALF_UP(无符号形式的四舍五入):1.1->1; 1.5->2.0; -1.1->-1.0; -1.5->-2.0

Java之BigDecimal的更多相关文章

  1. java中BigDecimal加减乘除基本用法

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数. 在实际应用中,需要对更大或者更小的数进 ...

  2. Java中BigDecimal的8种舍入模式

    java.math.BigDecimal 不可变的.任意精度的有符号十进制数.BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成. 如果为零或正数,则标度是小数点后的位 ...

  3. java的BigDecimal

    java的BigDecimal 一般设计到高精度的加法或乘法或者阶乘的求和积都会用到BigDecimal这个类. import java.util.*;import java.math.BigDeci ...

  4. java.math.BigDecimal类

    BigDecimal类用于高精度计算.一般的float型和Double型数据只可以用来做科学计算或者是工程计算,由于在商业计算中,要求的数字精度比较高,所以要用到java.math.BigDecima ...

  5. Java中BigDecimal的8种舍入模式是怎样的

    Java中BigDecimal的8种舍入模式是怎样的?下面长沙欧柏泰克软件学院和大家一起来学习下吧:  java.math.BigDecimal 不可变的.任意精度的有符号十进制数.BigDecima ...

  6. java.math.BigDecimal()的用法

    Java中简单的浮点数类型float和double是不能进行运算的,不光Java,很多语言都是这样. 我们运行下面程序你将会看到 public class TestMathDecimal { publ ...

  7. 九度OJ题目1137:浮点数加法 (JAVA)使用BigDecimal四个案例都通过了,但是超时了。

    题目描述: 求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式: P1P2...Pi.Q1Q2...Qj 对于整数部分,P1P2...Pi是一个非负整数 对于小数部分,Qj不等于0 输入: ...

  8. Java使用BigDecimal保留double、float运算精度、保留指定位数有效数字、四舍五入

    工具类 package --; import java.math.BigDecimal; /** * Created by kongqw on 2015/12/10. */ public final ...

  9. Java 使用BigDecimal类处理高精度计算

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的 ...

  10. 数据转换失败 java.math.BigDecimal cannot be cast to java.lang.String

    从接口获取到数据,在转换的时候出现错误:java.math.BigDecimal cannot be cast to java.lang.String 因为一开始用的是使用关键字进行强制转换,后来发现 ...

随机推荐

  1. S4 exercise -- 模块

    写一个用户登录验证程序,文件如下1234.json {"expire_date": "2021-01-01", "id": 1234, &q ...

  2. 配置 cxf-ws spring bean 文件

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  3. 安装hue-3.11.0

    1) 配置HDFS HttpFS和WebHDFS 如果HDFS是HA方式部署的,则只能使用HttpFS,而不能用WebHDFS. 2) 安装依赖: apr-iconv-1.2.1 confuse-3. ...

  4. hdu1002 A + B Problem II(高精度加法) 2016-05-19 12:00 106人阅读 评论(0) 收藏

    A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  5. PAT甲 1008. Elevator (20) 2016-09-09 23:00 22人阅读 评论(0) 收藏

    1008. Elevator (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The highest ...

  6. Lucene原理一

    Lucene 是一个高效的,基于Java 的全文检索库. 所以在了解Lucene之前要费一番工夫了解一下全文检索. 那么什么叫做全文检索呢?这要从我们生活中的数据说起. 我们生活中的数据总体分为两种: ...

  7. 四则运算 Python实现(杨浩政,张兆敏)

    四则运算 GitHub仓库:https://github.com/15crmor/Arithmetic 项目要求: 题目:实现一个自动生成小学四则运算题目的命令行程序说明: 说明: 自然数:0, 1, ...

  8. 如何在Windows应用商店中提交您的Windows 8.1 应用更新

    翘首以盼的Windows 8.1 不负众望的与大家见面了,与此同时也带来了全新的应用商店,小伙伴儿们要赶紧升级系统啦! 今天给大家介绍下如何提交一个Windows 8.1 的应用,其实微软针对这次系统 ...

  9. TCP协议通讯流程

    刚才网上找到的,觉得挺详细的,转来. tcp连接的三次握手大家肯定都熟了,可是有的人不一定对tcp断开的四次握手也很熟悉. 我在园子里面找到一张图,介绍的很好,现在转来!(该图片原博客地址:http: ...

  10. pgAdmin4 汉化