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. 模拟界面请求到web服务器

    客户端 package com.lsw.client; import java.io.*; import java.net.*; import java.util.*; public class HT ...

  2. 在 Pandas 中更改列的数据类型

    import pandas as pd import numpy as np a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0' ...

  3. 在qemu上运行BusyBox

    BusyBox 前文“在qemu环境中用gdb调试Linux内核”和“Initramfs 原理和实践”分别描述了怎么用qemu来运行一个编译好的内核,以及怎么指定initramfs,但都是简单的演示. ...

  4. Xamarin无法调试Android项目

    Xamarin无法调试Android项目   项目可以正常编译,生成APK,也可以通过右键菜单部署.但是一旦开启调试,就报错.错误信息如下: 没有为此解决方案配置选中要生成的项目   出现这种问题是因 ...

  5. JAVA内存泄漏解决办法

    JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...

  6. Kolla O版本部署

    Kolla O版部署和之前的版本还是有些区别的,环境还是all-in-one 基本准备: 关闭Selina和firewalld [root@kolla ~]# cat /etc/redhat-rele ...

  7. Python如何将RGB图像转换为Pytho灰度图像?

    我正尝试使用matplotlib读取RGB图像并将其转换为灰度.在matlab中,我使用这个: 1 img = rgb2gray(imread('image.png')); 在matplotlib t ...

  8. django中两张表有外键关系的相互查找方法,自定义json编码方法

    两张通过外键联系的表,如何在一张表上根据另一张表上的属性查找满足条件的对象集? 平常查找表中数据的条件是python中已有的数据类型,通过名字可以直接查找.如果条件是表中外键列所对应表的某一列,该如何 ...

  9. [BZOJ5303][HAOI2018]反色游戏(Tarjan)

    暴力做法是列异或方程组后高斯消元,答案为2^自由元个数,可以得60分.但这个算法已经到此为止了. 从图论的角度考虑这个问题,当原图是一棵树时,可以从叶子开始唯一确定每条边的选择情况,所以答案为1. 于 ...

  10. 利用arpspoof探取账户密码

    ---恢复内容开始--- > /proc/sys/net/ipv4/ip_forward 首先在kali里开启IP转发功能 arpspoof -t 被害人ip 网关ip -i eth0 例如 再 ...