Java中浮点数的精度问题 【转】
当您在计算Money的时候,请看好了!!!要不损失了别后悔!!!
现象1:
public static void main(String[] args) { System.out.println(0.030*100);//输出3.0 System.out.println(0.031*100);//输出3.1 System.out.println(0.032*100);//输出3.2 System.out.println(0.033*100);//输出3.3000000000000003 System.out.println(0.034*100);//输出3.4000000000000004 System.out.println(0.035*100);//输出3.5000000000000004 System.out.println(0.036*100);//输出3.5999999999999996 System.out.println(0.037*100);//输出3.6999999999999997 System.out.println(0.038*100);//输出3.8 System.out.println(0.039*100);//输出3.9 } |
现象2:
public static void main(String[] args) { BigDecimal b1 = new BigDecimal("0.236"); BigDecimal b2 = new BigDecimal(0.236); System.out.println(b1);//输出0.236 System.out.println(b2);//输出0.2359999999999999875655021241982467472553253173828125 } |
描述:
当我们使用一些“特殊的数字”进行运算时,或者调用BigDecimal中new BigDecimal(double val)进行构造的时候,将得到意想不到的结果。
原因:
Java中,浮点类型是依据IEEE754标准的。IEEE754定义了32位和64位双精度两种浮点二进制小数标准。采用二进制表示double,float等浮点数是不准确的。
同时BigDecimal的API声明,建议使用new BigDecimal(String val)进行构造,使用new BigDecimal(double val)进行构造的时候,将得到意想不到的结果(The results of this constructor can be somewhat unpredictable)。
解决办法(以0.236*100 = 23.599999999999998为例):
1、 通过String结合BigDecimal来转换。
String val = "0.236"; //使用new BigDecimal(String val)进行构造 BigDecimal a = new BigDecimal(""+val); BigDecimal b = new BigDecimal(""+100); //小数的位数与构造参数的位数一致 System.out.println(a.multiply(b));//输出23.600 |
2、 通过移位结合BigDecimal来转换
String val = "0.236"; //使用new BigDecimal(String val)进行构造 BigDecimal a = new BigDecimal(""+val); //向右移两位 a = a.movePointRight(2); System.out.println(a);//输出23.6 |
3、 使用保留小数位的方法来转换
double result = 0.236*100; System.out.println(result);//输出23.599999999999998 //计算保留result小数点后四位,以此类推,1后面几个零就是保留小数点后几位数.如下保留两位小数 result = (double)(Math.round(result*100)/100.0) ; System.out.println(result);//输出23.6 |
4、 使用DecimalFormat来确定小数点后位数
double val = 0.236*100; //保留小数点后两位,若保留三位为"#.000" DecimalFormat df = new DecimalFormat("#.00"); String str = df.format(val); System.out.println(Double.valueOf(str));//输出23.6 |
5、-----方法很多,一个即可
心得:
处理这样的精度问题方法很多,只要不是直接采用浮点数进行计算就行。
附加:
IEEE 754用科学记数法以底数为2的小数来表示浮点数。32位浮点数用1位表示数字的符号,用8位来表示指数,用23位来表示尾数,即小数部分。作为有符号整数的指数可以有正负之分。小数部分用二进制(底数2)小数来表示。对于64位双精度浮点数,用1位表示数字的符号,用11位表示指数,52位表示尾数。如下两个图来表示:
float(32位):
1位,符号位 |
幂(8位) |
尾数(32位) |
double(64位):
1位,符号位 |
幂(11位) |
尾数(52位) |
都是分为三个部分:
(1)一个单独的符号位s直接编码符号s。
(2)k位的幂指数E,移码表示。
(3)n位的小数,原码表示。
Java中浮点数的精度问题 【转】的更多相关文章
- 计算价格, java中浮点数精度丢失的解决方案
计算价格, java中浮点数精度丢失的解决方案
- java中浮点数的比较(double, float)(转)
问题的提出:如果我们编译运行下面这个程序会看到什么? public static void main(String args[]){ System.out.println(0.05+0.01); Sy ...
- jmeter 中 浮点数计算精度问题
jmeter 中 浮点数计算精度问题解决方法: 编写 beanshell 时使用 java.math.BigDecimal 方法构造,使用 BigDecimal 并且一定要用 String 来够造. ...
- Java 中浮点数---------BigDecimal和double(初探)
为什么要使用 bigdecimal? 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了 ...
- Java中浮点数能连续精确表示整数的范围
转自http://blog.csdn.net/seizef/article/details/5571783#ref_1,有删改. 先简单介绍一下浮点数在计算机中的组成,在Java中采用的浮点数表示法是 ...
- Java中浮点数的基础知识
偶然查看Math.round的JDK public static int round(float a) { if (a != 0x1.fffffep-2f) // greatest float val ...
- Java中浮点数的坑
基本数据类型 浮点数存在误差 浮点数有一个需要特别注意的点就是浮点数是有误差的,比如以下这段代码你觉得输出的什么结果: public class Demo { public static void m ...
- java第二周的学习知识4(对原码,补码,反码和java中浮点数计算不准确的总结)
原码:一个正数,转换为二进制位就是这个正数的原码.负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码. 但是原码有几个缺点,零分两种 +0 和 -0 .很奇怪是吧!还有,在进行不同符号的加法运 ...
- C/C++中浮点数输出精度的问题
本文使用C++语言书写,对于C的小伙伴们,如果编译不通过的话--就说明C里面没有这个内容,可以跳过 通常来说,我们书写程序主要只用整形变量 (signed/unsigned) (long/long l ...
随机推荐
- Uva - 177 - Paper Folding
If a large sheet of paper is folded in half, then in half again, etc, with all the folds parallel, t ...
- 4种方法让SpringMVC接收多个对象(转:http://blog.csdn.net/lutinghuan/article/details/46820023)
问题背景: 我要在一个表单里同时一次性提交多名乘客的个人信息到SpringMVC,前端HTML和SpringMVC Controller里该如何处理? 第1种方法:表单提交,以字段数组接收: 第2种方 ...
- 【一天一道LeetCode】#55. Jump Game
一天一道LeetCode系列 (一)题目 Given an array of non-negative integers, you are initially positioned at the fi ...
- SQLServer 基础
1当设计表时,对表进行结构性的修改(如将原来可以null的改为不可null),直接改则不允许保存修改,需要选择 工具----选项----designers—表设计器和数据库设计器---阻止保持要求重新 ...
- 使用钩子参与到TCP拥塞事件的处理中
TCP定义了几个拥塞事件,当这些事件发生时,我们可以通过TCP的拥塞控制算法,调用自定义的处理函数, 来做一些额外的事情的.也就是说,我们可以很简便的参与到TCP对拥塞事件的处理过程中. Author ...
- Markdown语法及编辑器
宗旨 Markdown 的目标是实现「易读易写」. 可读性,无论如何,都是最重要的.一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布,并且看起来不会像是由许多标签或是格式指令所构成. ...
- Android为什么使用Binder-android学习之旅(101)
基础知识 Android进程和linux进程一样,他们只运行在进程固有的虚拟空间中.一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间 ,用户空间是非共享的,内核空间是共享的,如下图: ...
- Cloud Carousel
<div class="carousel1" id="carousel1" > <a href="#"><im ...
- Bash的一些零星笔记
1.变量带入操作符 在脚本中,使用变量前做检查是很重要的.通过代入操作符,可以实现这方面的功能.比如当变量未赋值时为变量赋默认值,以及更多内容: ${parameter:-默认为空}:当paramet ...
- web集群时session同步的3种方法[转]
在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,一个登录用户,一会是登录状态,一会又不是 ...