当您在计算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. (NO.00001)iOS游戏SpeedBoy Lite成形记(二十三)

    现在还有一个视觉上的问题:玩家每次在游戏开始前选择某一赛道时,无法直观的看到所选的是哪条赛道.只能通过界面上方的gambleLabel中的文字非直观的看到.我们现在来完善它! 为了能让玩家清楚地看到, ...

  2. 【一天一道LeetCode】#55. Jump Game

    一天一道LeetCode系列 (一)题目 Given an array of non-negative integers, you are initially positioned at the fi ...

  3. Emotiv脑电设备与RDS机器人仿真初步测试

    Emotiv脑电设备与RDS机器人仿真初步测试 在脑电设备相关算法进行真实机器人测试前,有必要进行大量仿真验证算法,节约开发时间. 这里给我启发的Emotiv使用所参考的一些网址. 官网:https: ...

  4. C语言函数strstr()分析及实现

    原型:char *strstr(const char *str1, const char *str2); #include<string.h> 找出str2字符串在str1字符串中第一次出 ...

  5. Leetcode_49_Anagrams

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42744709 Given an array of stri ...

  6. Android Studio下使用NDK的流程

    我要重新拿回持之以恒徽章!! 老规矩,先说看能学会什么:ANDROID STUDIO下NDK的使用方法.JNI的基本使用方法,C语言调用JAVA的方法. 首先要下载NDK,如果你没有VPN可以来htt ...

  7. Mapreduce 框架解析

    MapReduce过程解析 一.客户端 Map-Reduce的过程首先是由客户端提交一个任务开始的. public static RunningJob runJob(JobConf job) thro ...

  8. TCP的核心系列 — SACK和DSACK的实现(四)

    和18版本不同,37版本把DSACK的检测部分独立出来,可读性更好. 37版本在DSACK的处理中也做了一些优化,对DSACK的两种情况分别进行处理. 本文主要内容:DSACK的检测.DSACK的处理 ...

  9. workbench的schema讲解一:(维度dimension设置的基本内容)

    维度名字尽量用英文:因为,saiku读取schema配置文件时,用中文会出现不可预知的错误.比如,引用维度用中文,就容易出现不可预估的错误.如果要显示中文:每个对象的caption字段里键入中文,则可 ...

  10. FFmpeg与VS2010

    编译FFmpeg是一件痛苦的事情,一般都直接使用Zeranoe FFmpeg Builds. 如果使用这个版本,需要注意ffmpeg的帮助里的一段话: To create import librari ...