问题

Java(其他编程语言也存在类似问题)中浮点数直接进行算术运算会导致精度丢失。

示例代码:

System.out.println("1.0 - 0.9 =" + (1.0 - 0.9));
System.out.println("0.1 + 0.02 =" + (0.1 + 0.02));
System.out.println("1.013 * 100 =" + (1.013 * 100));
System.out.println("123.3 / 100 =" + (123.3 / 100));

运行结果为:

解决方案

Java提供了BigDecimal类用来解决浮点数的运算。

BigDecimal提供了大量的构造方法用于生成一个BigDecimal对象,包括把基本类型、数字字符串、数字数组构造成BigDecimal对象。

这里以double类型数字转换为BigDecimal对象进行说明。常用有三种方式将double类型数字转换为BigDecimal对象。

  1. BigDecimal(double value):不推荐使用。生成的数值和value是一个近似数,不精确。
  2. BigDecimal(String value):推荐使用。
  3. BigDecimal.valueOf(double value):推荐使用。可以直接把一个double类型数值转换为精确的BigDecimal对象。

BigDecimal类型提供了相应方法实现算术运算,常用方法如下表所示,具体参数可以查询API文档。

方法 方法说明
add() 相加
subtract() 相减
multiply() 相乘
devide() 相除
pow() 幂运算

示例代码:

BigDecimal num1 = new BigDecimal("0.05");
BigDecimal num2 = new BigDecimal("0.01");
System.out.println("0.05 + 0.01 =" + (num1.add(num2)));
System.out.println("0.05 - 0.01 =" + (num1.subtract(num2)));
System.out.println("0.05 * 0.01 =" + (num1.multiply(num2)));
System.out.println("0.05 / 0.01 =" + (num1.divide(num2)));

  

运行结果:

自定义浮点数计算类

项目中如果要频繁进行浮点数计算,可以自定义一个浮点数计算类。

在进行除法运算过程中,如果需要进行精度控制,可以使用divide(BigDecimal divisor, int scale, int roundingMode)方法进行精度控制。sacale表示精度,roundingMode表示舍入方式。

示例代码:

public class MyArith {
/** 定义除法运算精度 */
private static final int DEFAULT_DIV_SCALE = 10; /** 单例模式 */
private MyArith() {
} /** 精确加法运算 */
public static double add(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.add(b2).doubleValue();
} /** 精确加法运算 */
public static double sub(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.subtract(b2).doubleValue();
} /** 精确乘法运算 */
public static double mul(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.multiply(b2).doubleValue();
} /** 精确除法运算 */
public static double div(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
// 精确到小数点后10位,四舍五入
return b1.divide(b2, DEFAULT_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
} /** 测试方法 */
public static void main(String[] args) {
System.out.println("0.05 + 0.01 = " + MyArith.add(0.05, 0.01));
System.out.println("1.0 + 0.42 = " + MyArith.sub(1.0, 0.42));
System.out.println("4.015 * 100 = " + MyArith.mul(4.015, 100));
System.out.println("123.3 / 99 = " + MyArith.div(123.3, 99)); }
}

  

运行结果:

JavaSE-30 BigDecimal类的使用的更多相关文章

  1. BIgInteger类和BigDecimal类的理解

    第一部分: 这两个类位于java.math包内,要使用它们必须在类前面引用该包:import java.math.BigInteger;和import java.math.BigDecimal; Bi ...

  2. Java学习——BigInteger类和BigDecimal类

    Java学习——BigInteger类和BigDecimal类 摘要:本文主要学习了用于大数字运算的BigInteger类和BigDecimal类. 部分内容来自以下博客: https://www.c ...

  3. Java匹马行天下之JavaSE核心技术——工具类

    Java匹马行天之JavaSE核心技术——工具类 一.Object类 java.lang.ObjectObject类是所有类直接或间接的父类 常用的方法: toString():以字符串形式返回对象的 ...

  4. JAVA集合类简要笔记 - 内部类 包装类 Object类 String类 BigDecimal类 system类

    常用类 内部类 成员内部类.静态内部类.局部内部类.匿名内部类 概念:在一个类的内部再定义一个完整的类 特点: 编译之后可生成独立的字节码文件 内部类可直接访问外部类私有成员,而不破坏封装 可为外部类 ...

  5. BigDecimal类

    如果需要精确的计算结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作. //========================================== ...

  6. Java大数处理类:BigInteger类和BigDecimal类

    当我们要处理非常大的数据时,平常用的数据类型已不足以表示,在Java中有两个类BigInteger和BigDecimal分别表示大整数类和大浮点数类,这两个类在理论上只要计算机内存足够大就能够表示无线 ...

  7. Java API —— BigDecimal类

    1.BigDecimal类概述  由于在运算的时候,float类型和double很容易丢失精度,演示案例.所以,为了能精确的表示.计算浮点数,Java提供了BigDecimal 不可变的.任意精度的有 ...

  8. 用BigDecimal类实现Fibonacci算法

    Fibonacci(N)=Fibonacii(N-1)+Fibonacci(N-2) 其中 Fibonacci(0)=0;Fibonacci(1)=1 用循环或则递归实现Fibonacci算法很简单, ...

  9. java.math.BigDecimal类

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

  10. Java基础知识强化88:BigDecimal类之BigDecimal类引入和概述 以及 BigDecimal的使用(加减乘除)

    1. BigDecimal类概述: 由于在运算的时候,float类型和double很容易丢失精度.所以为了能够精确的表达.计算浮点数,Java提供了BigDecimal. BigDecimal:不可变 ...

随机推荐

  1. bzoj 4557: [JLoi2016]侦察守卫【树形dp】

    设f[u][i]为u点向下覆盖至少i层并且处理完u的子树的最小代价,f[u][i]为u点向上覆盖至少i层并且处理完u的子树的最小代价 转移的话显然f[u][i]+=f[v][i-1],但是f[u][0 ...

  2. P5166 xtq的口令

    传送门 这题要是搞懂在干什么其实不难(虽然某个花了几个小时才搞明白的家伙似乎没资格这么说--) 假设所有人都没有听到老师的命令,我们从左到右考虑,对于当前的人,如果它没有观察者,那么肯定要让它听到老师 ...

  3. web移动端下拉加载数据简单实现

    //下拉加载在移动端会经常使用,有些小伙伴不清楚一些原理下面就简答的介绍一下 //首先需要监听window的滚动事件,下拉其实就是在监听window滚动事件 var pageNum = 1;//分页第 ...

  4. 修改 jq weui cityPicker.js原来的值

    1.对接后台接口,拿到返回来的值,注意数据格式要一样 var raw; $.ajax({ type: "GET", url: "/web/region/list.json ...

  5. PHP 遍历一个文件夹下所有文件和子文件夹的方法

    话不多说,直接上代码 <?php function my_dir($dir) { $files = []; if(@$handle = opendir($dir)) { while(($file ...

  6. JSP | 基础 | JSP状态管理 | Cookie

    Cookie : 是web服务器保存在客户端的一系列文本信息. Cookie的作用: 1.对特定的对象的追踪 2. 3. JSP中创建Cookie以及使用 创建Cookie对象 写入Cookie对象 ...

  7. ARC 100

    链接 https://arc100.contest.atcoder.jp/ C Linear Approximation 题解 把ai减去i后排序, 我们要的b就是排完序后的中位数 Code #inc ...

  8. C#方法拓展

    作用: “扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.” 要求: 1.拓展方法必须是在一个非嵌套.非泛型的静态类中定义.2.他至少有一个参数.3. ...

  9. C# 控制台如何播放音频文件

    OK,先看下代码: using System.Reflection; using System.Media; namespace ThePlay { class Program { static vo ...

  10. 【前端】Html5浏览器缓存 sessionStorage 与 localStorage

    一.sessionStorage: 浏览关闭会话结束就被清除:(不能跨页面) localStorage:永久保存: 二.使用 var storage = window.sessionStorage; ...