1、实际意义

在实际开发中,如果需要进行float或double的精确计算(尤其是财务计算),直接使用float或double是不行的(具体的例子看下边的代码的main方法的测试结果),需要使用BigDecimal。

2、代码

package com.xxx.util;

import java.math.BigDecimal;

/**
* 浮点数精准算法
*/
public class BigDecimalArithUtil { private static final int DIV_SCALE = 10;//除法精度(除不尽时保留10为小数) /** 小数精确加法 */
public static double add(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
return bd1.add(bd2).doubleValue();
} /** 小数精确减法 */
public static double sub(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
return bd1.subtract(bd2).doubleValue();
} /** 小数精确乘法 */
public static double mul(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
return bd1.multiply(bd2).doubleValue();
} /** 小数精确除法 */
public static double div(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
/*
* 当除不尽时,以四舍五入的方式(关于除不尽后的值的处理方式有很多种)保留小数点后10位小数
*/
return bd1.divide(bd2, DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
} public static void main(String[] args)
{
//测试加法
System.out.println("0.05+0.01="+BigDecimalArithUtil.add(0.05,0.01));
System.out.println("0.05+0.01="+(0.05+0.01));
//测试减法
System.out.println("1.0-0.42="+BigDecimalArithUtil.sub(1.0,0.42));
System.out.println("1.0-0.42="+(1.0-0.42));
//测试乘法
System.out.println("4.015*100="+BigDecimalArithUtil.mul(4.015,100));
System.out.println("4.015*100="+(4.015*100));
//测试除法
System.out.println("123.3/100="+BigDecimalArithUtil.div(123.3,100));
System.out.println("123.3/100="+(123.3/100));
} }

3、注意点

  • 上边的程序我用的是BigDecimal.valueOf(double x)来将double型的x封装成BigDecimal,查看源码如下:

        /**
    * 注意:这通常是将double和float转换为一个BigDecimal的最好方式
    */
    public static BigDecimal valueOf(double val) {
    return new BigDecimal(Double.toString(val));
    }

    在这里直接先将double转换为了String,然后使用如下构造方法再将String转换为BigDecimal

     public BigDecimal(String val)

    这是最好的做法。如果使用的是直接将double或float转换为BigDecimal的方式,也就是说使用的如下构造器,那么将可能得不到精确结果。(看注释)这一点可以用10.02*10.02来证明。

        /**
    * 注意:The results of this constructor can be somewhat unpredictable.
    * 该构造器的结果有时是不准确的
    */
    public BigDecimal(double val)
  • 在实际使用中还可能使用int和long来进行浮点数的精确计算(具体做法:将浮点数先乘以相应的倍数转化为int(<=9位十进制数)或long(<=18位十进制数),计算之后再除以之前的倍数,得出结果),而且该种方式的性能会更高,具体的int、long和BigDecimal各自的使用看《Effective Java(第二版)》第48条。
  • 需要指出的是,在实际开发中,BigDecimal的性能差的问题基本可以忽略,是浮点数精确计算的首选,而且根据上一条来看,如果将浮点数转化后的整数大于18位的话,也必须用BigDecimal

第二章 Java浮点数精确计算的更多相关文章

  1. Java浮点数精确计算

    BigDecimal是Java提供的一个不变的.任意精度的有符号十进制数对象.

  2. java面向对象编程——第二章 java基础语法

    第二章 java基础语法 1. java关键字 abstract boolean break byte case catch char class const continue default do ...

  3. 《深入理解java虚拟机》第二章 Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 2.2 运行时数据区域  

  4. 第二章Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 一.概述 对与Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每个new操作去写delete/free代码,不容易出现内存泄露和内存溢出问 题, ...

  5. 虚拟机--第二章java内存区域与内存溢出异常--(抄书)

    这是本人阅读周志明老师的<深入理解Java虚拟机>第二版抄写的,有很多省略,不适合直接阅读,需要阅读请出门左转淘宝,右转京东,支持周老师(侵权请联系删除) 第二章java内存区域与内存溢出 ...

  6. 浮点数运算结果不精确,以及用String来构造BigDecimal进行浮点数精确计算

    1.浮点数运算结果不精确 先看如下代码 System.out.println(1.0 - 0.8); System.out.println(0.2 + 0.1); System.out.println ...

  7. java 小数精确计算

    小数精确计算 System.out.println(2.00 -1.10);//0.8999999999999999 上面的计算出的结果不是 0.9,而是一连串的小数.问题在于1.1这个数字不能被精确 ...

  8. JAVA中精确计算金额BigDecimal

    package com.chauvet.utils; import java.math.BigDecimal; import java.text.DecimalFormat; import java. ...

  9. 第二章 Java 基本语法1

    2.1关键字 1.定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词). 2.特点:关键字中所有字母都是小写字母. 3.分类: 用于定义数据类型的关键字:byte.short.int.lo ...

随机推荐

  1. [js]正则篇

    一.正则基本概念 1.一种规则.模式.文本处理工具 2.强大的字符串匹配工具 3.在js中常与字符串函数配合使用 二.js正则写法 正则在js中以正则对象存在: (1)var re=new RegEx ...

  2. java jdbc深入理解(connection与threadlocal与数据库连接池和事务实)

    1.jdbc连接数据库,就这样子 Class.forName("com.mysql.jdbc.Driver");java.sql.Connection conn = DriverM ...

  3. centos 安装php7、pecl 、swoole、redis拓展

    一.更新yum源,安装php7 CentOS/RHEL 7.x: rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest- ...

  4. shell 规范

    代码风格规范 开头有“蛇棒” 所谓shebang其实就是在很多脚本的第一行出现的以”#!”开头的注释,他指明了当我们没有指定解释器的时候默认的解释器,一般可能是下面这样: #!/bin/bash 当然 ...

  5. 机器学习之路:python 集成分类器 随机森林分类RandomForestClassifier 梯度提升决策树分类GradientBoostingClassifier 预测泰坦尼克号幸存者

    python3 学习使用随机森林分类器 梯度提升决策树分类 的api,并将他们和单一决策树预测结果做出对比 附上我的git,欢迎大家来参考我其他分类器的代码: https://github.com/l ...

  6. 20162318 2018-2019-2《网络对抗技术》Exp0 Kali安装 Week1

    1.配置虚拟机 参考博客链接 2.安装kali与配置网络 参考博客链接 3.配置共享文件夹 参考博客链接 4.更换软件源 参考博客链接

  7. sgu 176 上下界网络流最小可行流带输出方案

    算法步骤: 1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流. 2. 加上刚才没有加上的那条边p 3. 再 ...

  8. tyvj 1004 滑雪 记忆化搜索

    滑雪 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.tyvj.cn/p/1004 Description     trs喜欢滑雪.他来 ...

  9. Linux服务器压测/拷机软件收集

    最近公司采购了一批服务器,于是收集了一些拷机软件来压测服务器硬件性能.硬件的稳定相对来说比较重要,7x24小时无间断运行,主要看三个硬件:CPU.内存.硬盘. 下面是收集的一些教程,可能网址已经失效了 ...

  10. 【Go入门教程7】面向对象(method、指针作为receiver、method继承、method重写)

    前面两章我们介绍了函数和struct,那你是否想过函数当作struct的字段一样来处理呢?今天我们就讲解一下函数的另一种形态,带有接收者(receiver)的函数,我们称为method method ...