当您在计算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. 如何在Git中撤销一切 | 干货

    翻译:李伟 审校:张帆 译自:Github JF杰微刊:如何在Git中撤销一切 任何一个版本控制系统中,最有用的特性之一莫过于 "撤销(undo)"操作.在Git中,"撤 ...

  2. SpriteBuilder中CCMotionStreak提示图片文件找不到

    今天写代码时遇到上述问题,代码如下: player.streak = [CCMotionStreak streakWithFade:3.f minSeg:1 width:30 color:[CCCol ...

  3. GCC内联函数:__builtin_types_compatible_p

    #if 0 - Built-in Function: int __builtin_types_compatible_p (type1, type2) You can use the built-in ...

  4. R12.2. Start and Stop Procedure

    R12.2. Start and Stop Procedure   Leave a comment Individual Components:  Application(Middle Tier) $ ...

  5. nodejs书籍

    http://product.dangdang.com/23371791.html#catalog https://www.byvoid.com/project/node http://www.ama ...

  6. 【Java编程】Java中的字符串匹配

    在Java中,字符串的匹配可以使用下面两种方法:         1.使用正则表达式判断字符串匹配         2.使用Pattern类和Matcher类判断字符串匹配 正则表达式的字符串匹配: ...

  7. 在FFMPEG中使用libRTMP的经验

    FFMPEG在编译的时候可以选择支持RTMP的类库libRTMP.这样ffmpeg就可以支持rtmp://, rtmpt://, rtmpe://, rtmpte://,以及 rtmps://协议了. ...

  8. 中国象棋游戏Chess(3) - 实现走棋规则

    棋盘的绘制和走棋参看博文:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制,中国象棋游戏Chess(2) - 走棋 现在重新整理之前写的代码,并且对于每个棋子的走棋规则都进行了限制,不像之前那 ...

  9. vi/vim下看十六进制文件

    :%!xxd --将当前文本转换为16进制格式. 查看内容是对应的.你可以后面看到对应的字符内容 :%!od --将当前文本转换为16进制格式. :%!xxd -c 12--将当前文本转换为16进制格 ...

  10. OpenCV GUI基本操作,回调函数,进度条,裁剪图像等

    代码为转载,出处找不到了,不贴了 工具条进度条: // ConvertColor.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #incl ...