在java中运行一下代码

System.out.println(2.00-1.10);
输出的结果是:0.8999999999999999
很奇怪,并不是我们想要的值0.9

再运行如下代码:
System.out.println(2.00f-1.10f);
输出结果:0.9

又正确了,为什么会导致这种问题?程序中为什么要尽量避免浮点数比较?

在java中浮点型默认是double的,及2.00和1.10都要在计算机里转换进行二进制存储,这就涉及到数据精度,出现这个现象的原因正是浮点型数据的精度问题。先了解下float、double的基本知识:
1. float和double是java的基本类型,用于浮点数表示,在java中float占4个字节32位,double占8个字节64位,一般比较适合用于工程测量计算中,其在内存里的存储结构如下:

float:

 符号位(1 bit) 指数(8 bit) 尾数(23 bit)

double:

符号位(1 bit) 指数(11 bit) 尾数(52 bit)

注意:从左到右是从低位到高位,而在计算机内部是采用逆序存储的。

2. System.out.println(2.00-1.10);中的1.10不能被计算机精确存储,以double类型数据1.10举例计算机如何将浮点型数据转换成二进制存储,
这里重点讲小数部分转换成二进制:
1.10整数部分就是1,转换成二进制1(这里整数转二进制不再赘述)
小数部分:0.1
0.1*2=0.2取整数部分0,基数=0.2
0.2*2=0.4取整数部分0,基数=0.4
0.4*2=0.8取整数部分0,基数=0.8
0.8*2=1.6取整数部分1,基数=1.6-1=0.6
0.6*2=1.2取整数部分1,基数=1.2-1=0.2
0.2*2=0.4取整数部分0,基数=0.4
.
.
.
.
直至基数为0。1.1用二进制表示为:1.000110...xxxx....(后面表示省略)
0.1 = 0*2^(-1)+0*2^(-2)+0*2^(-3)+1*2^(-4)+.........而double类型表示小数部分只有52位,当向后计算 52位后基数还不为0,那后面的部分只能舍弃,从这里可以看出float、double并不能准确表示每一位小数,对于有的小数只能无限趋向它。在计算机 中加减成除运算实际上最后都要在计算机中转换成二进制的加运算,由此,当计算机运行System.out.println(2.00-1.10);
时会拿他们在计算机内存中的二进制表示计算,而1.10的二进制表示本身就不准确,所以会出现0.8999999999999999的结果。

但为什么System.out.println(2.00f-1.10f);得出的结果是0.9呢。因为float精度没有double精度那么大,小数部分0.1二进制表示被舍去的比较多。

注意:

  • 程序中应尽量避免浮点数的比较
  • float、double类型的运算往往都不准确

解决方法:

使用BigDecimal提供的方法进行比较或运算,但要注意在构造BigDecimal的时候使用float、double的字符串形式构建,BigDecimal(String val);为什么不用BigDecimal(double val)API里写的比较清楚。

运算以减法为例:

BigDecimal b1 = new BigDecimal(Double.toString(2.00));

BigDecimal b2 = new BigDecimal(Double.toString(1.10));

double result = b1.subtract(b2).doubleValue();

Java中 float、double使用注意问题的更多相关文章

  1. java中float/double浮点数的计算失精度问题(转)

    如果我们编译运行下面这个程序会看到什么? public class Test  {    public static void main(String args[]) {                ...

  2. Java中float/double取值范围与精度

    Java浮点数 浮点数结构 要说清楚Java浮点数的取值范围与其精度,必须先了解浮点数的表示方法,浮点数的结构组成,之所以会有这种所谓的结构,是因为机器只认识01,你想表示小数,你要机器认识小数点这个 ...

  3. 神奇:java中float,double,int的值比较运算

    float x = 302.01f;    System.out.println(x == 302.01); //false  System.out.println(x == 302.01f); // ...

  4. Java中float和double转换的问题

    为什么double转float不会出现数据误差,而float转double却误差如此之大?   double d = 3.14; float f = (float)d; System.out.prin ...

  5. 精确计算java中float和double的精度

    [本文相关的代码放在github上.地址为:https://github.com/VigourJiang/StructuredFloat] Java中double类型的格式基本遵循IEEE 754标准 ...

  6. Java中float、double、long类型变量赋值添加f、d、L尾缀问题

    展开1. 添加尾缀说明 我们知道Java在变量赋值的时候,其中float.double.long数据类型变量,需要在赋值直接量后面分别添加f或F.d或D.l或L尾缀来说明.  其中,long类型最好以 ...

  7. Java中的Double类型计算

    一.问题的提出: 如果我们编译运行下面这个程序会看到什么?public class Test{    public static void main(String args[]){        Sy ...

  8. java中的double

    代码如下: Double d1 = 0.35; Double d2 = 0.1; System.out.println(d1+d2); 结果很不幸不是0.45,而是0.4499999999999999 ...

  9. java中float和double的区别

    float表示单精度浮点数在机内占4个字节,用32位二进制描述. double表示双精度浮点数在机内占8个字节,用64位二进制描述.浮点数在机内用指数型式表示,分解为:数符,尾数,指数符,指数四部分. ...

随机推荐

  1. ORM对象关系映射之GreenDAO建立多表关联

    利用GreenDAO可以非常方便的建立多张表之间的关联 一对一关联 通常我们在操作数据库的时候,我们往往不是单独的对一张表进行操作,而是对这张表的操作会联动的影响另外一张表或者多张表,比如:现在有两张 ...

  2. nodejs书籍

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

  3. LeetCode之“树”:Validate Binary Search Tree

    题目链接 题目要求: Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is ...

  4. sql的having深入理解;group by只返回一组的一行,compute更好

    Having where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行. having 子句的作用是 ...

  5. This version of the rendering library is more recent than your version of ADT plug-in. Please update

    预览layout.xml文件时提示: This version of the rendering library is more recent than your version of ADT plu ...

  6. FNDCPASS Troubleshooting Guide For Login and Changing Applications Passwords

    In this Document   Goal   Solution   1. Error Starting Application Services After Changing APPS Pass ...

  7. 【34】包含min函数的stack

    题目: 实现一个包含min函数的栈,min和push,pop都是o(1)时间 思路: 采用一个辅助的栈,来存储不同阶段的最小值 - 代码: push(int value){ //data是数据栈,mi ...

  8. Effective STL 为包含指针的关联容器指定比较类型

    // 为包含指针的关联容器指定比较类型.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <set> #incl ...

  9. vicoapp使用备忘

    vico是一个模式编辑器,意味着没用过vi之类编辑器的童鞋用起来肯定觉得很不习惯. 模式切换 i:切至编辑模式,在光标前插入 a:切至编辑模式,在在光标后插入 I:类似于i,不过在行首插入 esc键: ...

  10. ruby写一个文件内容相似性比较的代码

    1.相似度定义 我们定义,则,我们设,则,|C|=s,则相似度p=,p(0,1) 2.相似度检测算法设计 算法设计: 定义4个字符为一个字符串,将T1,T2分割成若干字符串,若剩余字符不足4个,则以空 ...