Java中解决浮点数精度的问题
来源:互联网 发布:老虎机控制器软件下载 编辑:程序博客网 时间:2024/05/18 03:54
转载于:https://my.oschina.net/roll1987/blog/753979
问题描述
在项目中用Java做浮点数计算时,发现对于4.015*100这样的计算,结果不是预料中的401.5,而是401.49999999999994。如此长的位数,对于显示来说很不友好。
问题原因:浮点数表示
查阅相关资料,发现原因是:计算机中的浮点数并不能完全精确表示。例如,对于一个double型的38414.4来说,计算机是这样存储它的:
- 转成二进制:1001011000001110.0110011001100110011001100110011001100
- 转成科学计数法:1.0010110000011100110011001100110011001100110011001100×2^15
- double型编码格式是这样的:double符号位1位阶码11位尾数52位
- 符号位:正数统一是0
- 阶码:15是正数,因此最高位是1,最低位减1,为10000001110
- 尾数:去掉最高位默认的1,为0010110000011100110011001100110011001100110011001100
- 组合起来,最终得到的编码是:0 10000001110 0010110000011100110011001100110011001100110011001100
从这里可以看出来,主要原因在于二进制编码使得小数部分无法完全精确表示,例如0.4 = 0.25 + 0.125 + ...,只能无限接近。所以在对浮点数做计算时会产生精度误差。
解决办法:高精度
Java中的BigDecimal可以支持任意精度的浮点数运算。在《Effective Java 》这本书中建议:float 和double 用来做科学计算或者是工程计算,而在商业计算中使用java.math.BigDecimal 。
BigDecimal有多种构造方法,如BigDecimal(double),BigDecimal(String),需要注意的是:构造参数为String类型时才能保证不丢失精度,因为double类型本身就是不完全精确的。故需要写成这样:BigDecimal("0.02")。
double类型的基本运算都能在BigDecimal中找到相对应的方法。另外,BigDecimal还可以配合NumberFormat做格式化输出。
BigDecimal在做运算的时候都会生成新的BigDecimal对象,因此相对double来说会带来更多的性能开销。
高精度实现初探
那么BigDecimal是如何做到能够表示任意精度的呢?这里只做一个初步的分析。
首先看BigInteger的实现。普通的int型是32位,因此有范围限制。BigInteger中有成员变量int[] mag,这样变长的int数组使得表示任意大小的整数成为可能。
再看BigDecimal的实现。它的官方介绍中说,任意一个BigDecimal都可以表示为unscaledValue × 10^-scale的形式。unscaledValue是一个任意大小的整数,在源代码中对应BigInteger intVal这个成员变量;scale是阶数,在源代码中对应int scale这个变量。这样就在BigInteger的基础上得到了BigDecimal的实现。
更细节的内容可以自行阅读源码做进一步分析。
- Java中解决浮点数精度的问题
- Java中解决浮点数精度的问题
- Java中解决浮点数精度的问题
- JAVA中浮点数的精度问题
- Java中浮点数的精度问题
- Java中浮点数的精度问题
- JAVA中浮点数的精度问题
- 浮点数精度丢失问题的解决
- Java中浮点数相见,精度问题
- java中floatdouble浮点数的计算失精度问题
- JS中浮点数精度的问题
- js中浮点数的精度问题
- java中浮点数的精度
- java 浮点数精度问题
- JAVA浮点数精度问题
- Java浮点数精度问题
- 【Java】解决计算浮点数精度问题(BigDecimal)
- 浮点数的精度问题
- iOS-关于UINavigationController的title不显示问题
- jQuery JS 获取时间函数集 取时间的一部分
- Oracle中不同条件的日期查询
- 单例模式
- 正则匹配超链接
- Java中解决浮点数精度的问题
- 别在最能吃苦的年纪选择了安逸
- Java httpClient 请求 可以在SpringMvc中使用
- 无刷新多张图片预览
- Solr 4.5.1 搜索引擎 环境搭建
- $(document).ready(function() {});
- 王朝
- 第十二周 求 1*3*5*...*n的值
- GPS导航电文介绍