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 ...
随机推荐
- 基于VB中WINSOCK控件的网上象棋系统的实现
本文发表在<微型机与应用>杂志2001年第3期. 基于VB中WINSOCK控件的网上象棋系统的实现 马根峰1 , 孙艳2 , 王平1 (1.重庆邮电学院自动化学院,重庆,40006 ...
- Volley学习小结
1.概述 volley英文即是"齐射,并发",是谷歌在2013年推出的网络通信库,有如下特点: [1]通信更快,更简单 [2]Get.Post网络请求以及网络数据图像的高效的异步请 ...
- mysql进阶(八)怎么对varchar类型排序问题
MySQL中怎么对varchar类型排序问题 asc 升级 desc降序 在mysql默认order by 只对数字与日期类型可以排序,但对于varchar字符型类型排序好像没有用了,下面我来给各位同 ...
- Android4.0Sd卡移植之使用vold自动挂载sd卡
在cap631平台上移植android4.0,发现内核驱动没有任何问题,能够读写,当总不能挂载. 后来发现是因为自动挂载需要vold的支持.vold程序负责检查内核的 sysfs 文件系统,发现有SD ...
- Android For JNI(一)——JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序,使用C启动JAVA程序
Android For JNI(一)--JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序 当你的Android之旅一步步的深入的时候,你其实会发现,很多东西都必须去和framew ...
- 高斯混合模型和EM算法
使用期望最大化算法(Expectation-Maximization)来进行密度估计(density estimation). 与k-means一样,给定的训练样本是,我们将隐含类别标签用表示.与k- ...
- 新版MATERIAL DESIGN 官方动效指南(一)
Google 刚发布了新版Material Design 官方动效指南,全文包括三个部分:为什么说动效很重要?如何制作优秀的Material Design动效及转场动画,动效的意义.新鲜热辣收好不谢! ...
- android 高仿京东
android 高仿京东源码,两年前的作品,最近发现一些老代码,发布出来给初学者学习,下面附上几张展示的效果,有需要的请到下面地址下载,记得stare哦 https://github.com/xian ...
- C语言在linux内核中do while(0)妙用之法
为什么说do while(0) 妙?因为它的确就是妙,而且在linux内核中实现是相当的妙,我们来看看内核中的相关代码: #define db_error(fmt, ...) \ do { \ fpr ...
- vs 2010调用matlab dll显示窗口核心代码
matlab代码: figure('NumberTitle','off','menubar','none','toolbar','none','name','Topo Image'); x=0:pi/ ...