Java中的Double类型的精度计算
来源:互联网 发布:企业网站cms 编辑:程序博客网 时间:2024/06/12 15:11
Java中的Double类型计算
一、问题的提出:
如果我们编译运行下面这个程序会看到什么?
public class Test{
public static void main(String args[]){
System.out.println(0.05+0.01);
System.out.println(1.0-0.42);
System.out.println(4.015*100);
System.out.println(123.3/100);
}
};
你没有看错!结果确实是
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
Java中的简单浮点数类型float和double不能够进行运算。不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。
这个问题相当严重,如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。
在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。现在让我们看看如何解决这个问题。
四舍五入
我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数,我们只能象这样(保留两位):
public double round(double value){
return Math.round(value*100)/100.0;
}
非常不幸,上面的代码并不能正常工作,给这个方法传入4.015它将返回4.01而不是4.02,如我们在上面看到的
4.015*100=401.49999999999994
因此如果我们要做到精确的四舍五入,不能利用简单类型做任何运算
java.text.DecimalFormat也不能解决这个问题:
System.out.println(new java.text.DecimalFormat("0.00").format(4.025));
输出是4.02
二、精确计算
在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal
我们如果需要精确计算,非要用String来够造BigDecimal不可!在《Effective Java》一书中的例子是用String来够造BigDecimal的
下面提供计算的代码:
(注意:divide方法中推荐使用枚举RoundingMode.HALF_UP)
1 package com.wetalk.wbs.bas.util; 2 3 import java.io.Serializable; 4 import java.math.BigDecimal; 5 import java.math.RoundingMode; 6 7 /** 8 * double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型 9 * 整型地方法适合于货币精度已知的情况,比如12.11+1.10转成1211+110计算,最后再/100即可10 * 以下是摘抄的BigDecimal方法:11 */12 public class DoubleUtil implements Serializable {13 private static final long serialVersionUID = -3345205828566485102L;14 // 默认除法运算精度15 private static final Integer DEF_DIV_SCALE = 2;16 17 /**18 * 提供精确的加法运算。19 *20 * @param value1 被加数21 * @param value2 加数22 * @return 两个参数的和23 */24 public static Double add(Double value1, Double value2) {25 BigDecimal b1 = new BigDecimal(Double.toString(value1));26 BigDecimal b2 = new BigDecimal(Double.toString(value2));27 return b1.add(b2).doubleValue();28 }29 30 /**31 * 提供精确的减法运算。32 *33 * @param value1 被减数34 * @param value2 减数35 * @return 两个参数的差36 */37 public static double sub(Double value1, Double value2) {38 BigDecimal b1 = new BigDecimal(Double.toString(value1));39 BigDecimal b2 = new BigDecimal(Double.toString(value2));40 return b1.subtract(b2).doubleValue();41 }42 43 /**44 * 提供精确的乘法运算。45 *46 * @param value1 被乘数47 * @param value2 乘数48 * @return 两个参数的积49 */50 public static Double mul(Double value1, Double value2) {51 BigDecimal b1 = new BigDecimal(Double.toString(value1));52 BigDecimal b2 = new BigDecimal(Double.toString(value2));53 return b1.multiply(b2).doubleValue();54 }55 56 /**57 * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。58 *59 * @param dividend 被除数60 * @param divisor 除数61 * @return 两个参数的商62 */63 public static Double divide(Double dividend, Double divisor) {64 return divide(dividend, divisor, DEF_DIV_SCALE);65 }66 67 /**68 * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。69 *70 * @param dividend 被除数71 * @param divisor 除数72 * @param scale 表示表示需要精确到小数点以后几位。73 * @return 两个参数的商74 */75 public static Double divide(Double dividend, Double divisor, Integer scale) {76 if (scale < 0) {77 throw new IllegalArgumentException("The scale must be a positive integer or zero");78 }79 BigDecimal b1 = new BigDecimal(Double.toString(dividend));80 BigDecimal b2 = new BigDecimal(Double.toString(divisor));81 return b1.divide(b2, scale,RoundingMode.HALF_UP).doubleValue();82 }83 84 /**85 * 提供指定数值的(精确)小数位四舍五入处理。86 *87 * @param value 需要四舍五入的数字88 * @param scale 小数点后保留几位89 * @return 四舍五入后的结果90 */91 public static double round(double value,int scale){92 if(scale<0){93 throw new IllegalArgumentException("The scale must be a positive integer or zero");94 }95 BigDecimal b = new BigDecimal(Double.toString(value));96 BigDecimal one = new BigDecimal("1");97 return b.divide(one,scale, RoundingMode.HALF_UP).doubleValue();98 }99 }
- Java中的Double类型的精度计算
- double类型精度计算
- JAVA中double类型计算精度控制
- Java 中double变量的精度计算
- Java控制double类型的精度
- Java中Double类型的运算精度
- java中double、float类型计算精度丢失问题
- java double float 精度计算
- java double 计算损失精度
- Java计算double精度问题
- java double 计算损失精度
- JAVA计算double精度丢失
- java double类型精度问题解决
- java double类型精度控制
- double 计算精度的问题
- double类型计算精度确实问题
- 精确计算java中float和double的精度
- java中Double类型的运算精度丢失的问题
- Android开发者2017年最值得关注的25个库
- 谈谈反爬虫“政策与对策”
- QSS风格QTabWidget美化
- Codeforces Round #439 A
- 内部类和String类常用方法
- Java中的Double类型的精度计算
- 《Python学习手册》学习笔记(14)之第14章迭代器和解析,第一部分(关键词:编程语言/Python/迭代器/解析/迭代器协议)
- map 与 set 简单用法
- java提高篇(14)--ByteArrayInputStream和ByteArrayOutputStream类用法
- 《Python学习手册》学习笔记(15)之第15章文档(关键词:编程语言/Python/文档/文档字符串/PyDoc)
- html/jQuery获取窗口宽度/高度
- Codeforces Round #439 (Div. 2) A-C题解
- STM32之IO输出方式理解
- 《Python学习手册》学习笔记(16)之第16章函数基础(关键词:编程语言/Python)