当您在计算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. Swift基础之Delegate方法的使用

    本文简单介绍了使用Delegate方法的进行值的传递,改变上一个界面的字体大小和颜色 首先创建一个导航视图: let viewC = ViewController();        let navi ...

  2. (NO.00001)iOS游戏SpeedBoy Lite成形记(二十六)

    到目前为止,选手跑到终点时仿佛没什么激动人心的事情发生呢?貌似需要添加一些胜利的特效啊! 前面说好的不添加特效,只完成游戏功能的诺言呢? T T 我们主要想实现这样一个特效效果: 1.胜利的玩家突出显 ...

  3. LCS问题(最长公共子序列)-动态规划实现

    问题描述: 问题] 求两字符序列的最长公共字符子序列 注意: 并不要求子串(字符串一)的字符必须连续出现在字符串二中. 思路分析: 最优子结构和重叠子问题的性质都具有,所以要采取动态规划的算法 最长公 ...

  4. saiku中文查询(鉴于有人提问:saiku执行mdx,有中文报错)

    有人问我saiku的中文查询问题: saiku默认执行英文,很多人,在mysql里录入了中文,使用sql语言查询没有问题. 可是,用saiku的mdx查询,就会报错. 这是因为mysql默认支持中文查 ...

  5. JQuery UI - resizable

     ·概述 resizable插件可以让选中的元素具有改变尺寸的功能. 官方示例地址:http://jqueryui.com/demos/resizable/ 所有的事件回调函数都有两个参数:eve ...

  6. Gradle 1.12用户指南翻译——第三十五章. Sonar 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  7. nfc近场通信

    NFC简介: Near Field Communication 近场通信,是一种数据传输技术. 与wifi.蓝牙.红外线等数据传输技术的一个主要差异就是有效距离一般不能超过4cm. NFC支持3种工作 ...

  8. 速度之王 — LZ4压缩算法(二)

    LZ4 (Extremely Fast Compression algorithm) 项目:http://code.google.com/p/lz4/ 作者:Yann Collet 本文作者:zhan ...

  9. OpenCV OpenGL手写字符识别

    另外一篇文章地址:这个比较详细,但是程序略显简单,现在这个程序是比较复杂的 http://blog.csdn.net/wangyaninglm/article/details/17091901 整个项 ...

  10. EBS R12安装升级(FRESH)(二)

    3 Linux系统设置 这一节步骤基本都在终端root用户下进行. 自行熟悉vi或其他文本工具的用法. 3.1 host-only外网连接 如果用的NAT模式这一节略过. 右击当前主机连接外网的网卡, ...