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 ...
随机推荐
- Python进阶 函数式编程和面向对象编程等
函数式编程 函数:function 函数式:functional,一种编程范式.函数式编程是一种抽象计算机的编程模式. 函数!= 函数式(如计算!=计算机) 如下是不同语言的抽象 层次不同 高阶函数: ...
- Mahout kmeans聚类
Mahout K-means聚类 一.Kmeans 聚类原理 K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一.K-means算法的基本思想是:以空间中k个点为中心进行聚 ...
- 图像检索:CEDD(Color and Edge Directivity Descriptor)算法
颜色和边缘的方向性描述符(Color and Edge Directivity Descriptor,CEDD) 本文节选自论文<Android手机上图像分类技术的研究>. CEDD具有抽 ...
- UML之对象图
对象图对包含在类图中的事物的实例建模,对象图显示了在某一时间点上一组对象以及他们之间的关系.对象图用于对系统的静态设计视图或静态交互视图建模,这包括对某一时刻的系统快照建模,表示出对象集.对象的状态以 ...
- 机器人操作系统ROS(indigo)与三维仿真软件V-Rep(3.2.1)通信接口使用笔记
关键字:ROS(indigo),V-Rep(3.2.1), vrep_ros_bridge(lagadic). vrep_ros_bridge提供了V-Rep和ROS之间的通信接口,可以实现使用ROS ...
- Android Studio Gradle Configuration Errors总结
初次看到这个错误,我从下手Error:Configuration with name 'default' not found. 只知道这是由于android的grad项目构建的时候出现的错误,但是具 ...
- OpenCV——PS 图层混合算法 (四)
具体的算法原理可以参考 PS图层混合算法之四(亮光, 点光, 线性光, 实色混合) // PS_Algorithm.h #ifndef PS_ALGORITHM_H_INCLUDED #define ...
- CRM客户关系管理系统(十二)
十二章.学员报名流程开发 2 12.1.学员报名合同和证件信息上传 功能: 必须勾选报名合同协议 必须上传个人证件信息 最多只能上传三个文件 文件大小2M以内 列出已上传文件 (1)crm/urls ...
- eclipse中tomcat内存溢出设置
Eclipse里启动Tomcat,配置内存大小 2009年12月11日 星期五 10:50 一般安装完eclipse之后,在安装目录下你应该可以看到有一个 eclipse.ini 文件,对了,就是在这 ...
- DIV与SPAN之间有什么区别
DIV与SPAN之间有什么区别 DIV 和 SPAN 元素最大的特点是默认都没有对元素内的对象进行任何格式化渲染.主要用于应用样式表(共同点). 两者最明显的区别在于DIV是块元素,而SPAN是行内元 ...