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. grep、find命令整理

    一.grep格式: grep [选项]... PATTERN [FILE]...(默认的PATTERN是一个基本的正则表达式(BRE)) 参数选项 1.杂项: -s, --no-messages 不显 ...

  2. MySQL用户授权 和 bin-log日志 详解和实战

    看了上一篇博文的发布时间,到目前已经有三个月没更新博文了.这三个月经历了很多事情,包括工作.生活和感情等等.由于个人发展的原因,这个月准备换工作啦.在这段时间,我会把Web大型项目中所接触到的技术都总 ...

  3. ref:详解MYSQL数据库密码的加密方式及破解方法

    ref:https://blog.csdn.net/paul123456789io/article/details/53081921 MySQL数据库用户密码跟其它数据库用户密码一样,在应用系统代码中 ...

  4. JAVA语言中的运算符和表达式

    JAVA——运算符 按运算符要求的运算符个数可分为一元.二元.三元运算符: 一元运算符有一个操作数:如正数或者负数前面的“+”.“—”,和自增“++”.自减“- -”. 二元运算符有两个操作数:如除法 ...

  5. tkinter-clock实例

    模仿着前辈的脚步,画了个临时的时钟显示: 代码如下: # coding:utf-8 from tkinter import * import math,time global List global ...

  6. 解决在ubuntu环境下, sublime不能输入中文的问题

    sublime text很好用,但是ubuntu下不能输入中文,这是一个很大的问题.网上已经有很多方法,这里将我自己使用的方法记录总结一下 首先,将你的操作系统升级到最新版: sudo apt-get ...

  7. MongoDB复制原理

    ##mongodb复制(主从服务器数据备份, 一个主服务器可以有很多个从服务器) #mongodb的复制至少需要两个节点.其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据 ...

  8. Centos 安装 WPS

    Linux有自己的一套类是Office的办公软件:LibreOffice,但是不是很友好,幸好WPS有Linux版本. 安装步骤: 1.安装依赖包 yum install libpng12 yum i ...

  9. ngx_lua配置及应用

    一.说明 这里不对lua语言本身及其编译器运行环境等做介绍,以下所有介绍前提对lua相关有所了解. 二.ngx_lua介绍 原理 ngx_lua将Lua嵌入Nginx,可以让Nginx执行Lua脚本, ...

  10. 502 解决:[WARNING] fpm_children_bury

    查过网上的资源,基本都是认为是php线程打开文件句柄受限导致的错误.具体的解决的办法如下:   1.提升服务器的文件句柄打开打开 /etc/security/limits.conf : (增加) * ...