当您在计算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中浮点数的精度问题 【转】的更多相关文章

  1. 计算价格, java中浮点数精度丢失的解决方案

    计算价格, java中浮点数精度丢失的解决方案

  2. java中浮点数的比较(double, float)(转)

    问题的提出:如果我们编译运行下面这个程序会看到什么? public static void main(String args[]){ System.out.println(0.05+0.01); Sy ...

  3. jmeter 中 浮点数计算精度问题

    jmeter 中 浮点数计算精度问题解决方法: 编写 beanshell 时使用 java.math.BigDecimal 方法构造,使用 BigDecimal 并且一定要用 String 来够造. ...

  4. Java 中浮点数---------BigDecimal和double(初探)

    为什么要使用 bigdecimal? 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了 ...

  5. Java中浮点数能连续精确表示整数的范围

    转自http://blog.csdn.net/seizef/article/details/5571783#ref_1,有删改. 先简单介绍一下浮点数在计算机中的组成,在Java中采用的浮点数表示法是 ...

  6. Java中浮点数的基础知识

    偶然查看Math.round的JDK public static int round(float a) { if (a != 0x1.fffffep-2f) // greatest float val ...

  7. Java中浮点数的坑

    基本数据类型 浮点数存在误差 浮点数有一个需要特别注意的点就是浮点数是有误差的,比如以下这段代码你觉得输出的什么结果: public class Demo { public static void m ...

  8. java第二周的学习知识4(对原码,补码,反码和java中浮点数计算不准确的总结)

    原码:一个正数,转换为二进制位就是这个正数的原码.负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码. 但是原码有几个缺点,零分两种 +0 和 -0 .很奇怪是吧!还有,在进行不同符号的加法运 ...

  9. C/C++中浮点数输出精度的问题

    本文使用C++语言书写,对于C的小伙伴们,如果编译不通过的话--就说明C里面没有这个内容,可以跳过 通常来说,我们书写程序主要只用整形变量 (signed/unsigned) (long/long l ...

随机推荐

  1. 海量数据挖掘MMDS week3:流算法Stream Algorithms

    http://blog.csdn.net/pipisorry/article/details/49183379 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  2. VC2010工程依赖不再自动链接

    发现 VC2010 Express  设置了 Project Dependencies 之后并没有自动链接. 而在VC2008中工程依赖不仅影响构建顺序,也会自动链接依赖项. 具体说明见: http: ...

  3. NSString/NSMutable字符串——韩俊强…

    1.OC基本数据类型(简单铺垫) //   NSInteger  在64 位下相当于long,在非64位下相当于 int: //    CGFloat 在64位下相当于double  在非64位下相当 ...

  4. crontab 任务程序执行乱码的问题

    今天碰到一个坑爹的问题,定时用php程序从远程的mssql读取数据,并写入到mysql中,手动用php执行程序的时候,程序运行没有问题,但当用crontab任务定时执行php程序的时候就出问题了,插入 ...

  5. MTK Android software Tools工具的说明

    MTK发布的Android software Tools工具包,里面包含了很多的MTK工具,如下是简要说明及学习文档 MTK Android software Tools工具的说明如下: 工具 说明 ...

  6. RecyclerView添加Header和Footer

    使用过RecyclerView的同学就知道它并没有添加header和footer的方法,而ListView和GirdView都有,但是开发过程中难免有需求需要添加一个自定义的header或者foote ...

  7. Android监听电池状态

    监听电池状态只需要接收Intent.ACTION_BATTERY_CHANGED的广播即可,当电池状态发生变化时会发出广播. 1.运行状态如下图: (1)连接USB时的状态 (2)断开USB时的状态 ...

  8. C语言内嵌汇编(arm-v7)----加减乘移位

    在现代嵌入式操作系统中,汇编语言当然必不可少,汇编语言的优势就是执行速度快.如果在C语言的代码中,在关键的地方内嵌汇编,那么效率将会大大的提高,我们来看看代码: #include <stdio. ...

  9. 面试之路(27)-链表中倒数第K个结点

    代码的鲁棒性: 所谓的鲁棒性是指能够判断输入是否合乎规范,能对不和规范的程序进行处理. 容错性是鲁棒性的一个重要体现. 防御性编程有助于提高鲁棒性. 切入正题,我可不是标题党: 链表倒数第k个节点 列 ...

  10. Nginx的内部(进程)模型

    nginx是以多进程的方式来工作的,当然nginx也是支持多线程的方式的,只是我们主流的方式还是多进程的方式,也是nginx的默认方式.nginx采用多进程的方式有诸多好处. (1)nginx在启动后 ...