文档章节

Java 浮点数 float和double类型的表示范围和精度

城固如春
 城固如春
发布于 2017/09/09 15:14
字数 1084
阅读 7
收藏 0

隐约记得,浮点数判断大小好像有陷阱,因为底层的二进制数不能精确表示所有的小数。有时候会产生让人觉得莫名其妙的事情。

如在java中,  

        0.99999999f==1f //true 

        0.9f==1f //false

要明白这些,首先要搞清楚float和double在内存结构

 

1、内存结构

float和double的范围是由指数的位数来决定的。
float的指数位有8位,而double的指数位有11位,分布如下:

 

float类型的存储方式

float:

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

            double类型数据的存储方式


double:
        1bit(符号位) 11bits(指数位) 52bits(尾数位)
于是,float的指数范围为-128~+127,而double的指数范围为-1024~+1023,并且指数位是按补码的形式来划分的。
其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。
float的范围为-2^128 ~ +2^127,也即-3.40E+38 ~ +3.40E+38;double的范围为-2^1024 ~ +2^1023,也即-1.79E+308 ~ +1.79E+308。
 

2. 精度

float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。
float:2^23 = 8388608,一共七位,由于最左为1的一位省略了,这意味着最多能表示8位数: 2*8388608 = 16777216 。有8位有效数字,但绝对能保证的为7位,也即float的精度为7~8位有效数字
double:2^52 = 4503599627370496,一共16位,同理,double的精度为16~17位

 

之所以不能用f1==f2来判断两个数相等,是因为虽然f1和f2在可能是两个不同的数字,但是受到浮点数表示精度的限制,有可能会错误的判断两个数相等!

我们可以用下面这段代码检验一下:

  1. float f1 = 16777215f;  
  2. for (int i = 0; i < 10; i++) {  
  3.     System.out.println(f1);  
  4.     f1++;  
  5. }  

 

对于小数来说,更容易会因为精度而出错误。

 

  1. float f = 2.2f;  
  2. double d = (double) f;  
  3. System.out.println(d);   
  4. f = 2.25f;  
  5. d = (double) f;  
  6. System.out.println(d);   


输出结果为:

        2.200000047683716
        2.25

对于这种简单数的输出结果会是这样,是简直无法忍受的。

其实通过上面关于两种存储结果的介绍,我们已经大概能找到答案。首先我们看看2.25的单精度存储方式,转化为2进制位便是10.01,整理为1.001*2 很简单 

于是我们可以写出2.25的内存分布: 
        符号位为:0
        指数为1,用补码表示 0000 0001,转为移码就是1000 0001。
        尾数位为0010 0000 0000 0000 0000 000

而2.25的双精度表示为:0 100 0000 0001 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000,这样2.25在进行强制转换的时候,数值是不会变的,而我们再看看2.2呢,2.2用科学计数法表示应该为:将十进制的小数转换为二进制的小数的方法为将小数*2,取整数部分,所以0.282=0.4,所以二进制小数第一位为0.4的整数部分0,0.4×2=0.8,第二位为0,0.8*2=1.6,第三位为1,0.6×2 = 1.2,第四位为1,0.2*2=0.4,第五位为0,这样永远也不可能乘到=1.0,得到的二进制是一个无限循环的排列 00110011001100110011... ,对于单精度数据来说,尾数只能表示24bit的精度,所以2.2的float存储为:

单精度数202的存储方式

但是这样存储方式,换算成十进制的值,却不会是2.2的,因为十进制在转换为二进制的时候可能会不准确,如2.2,而double类型的数据也存在同样的问题,所以在浮点数表示中会产生些许的误差,在单精度转换为双精度的时候,也会存在误差的问题,如下面的代码,输出结果就不一样:

 

  1. float f = 2.2f;  
  2. double d = (double) f;  
  3. System.out.println(f);  
  4. System.out.println(d);  

 

对于能够用二进制表示的十进制数据,如2.25,这个误差就会不存在,所以会出现上面比较奇怪的输出结果。

 

本文转载自:http://blog.csdn.net/zq602316498/article/details/41148063

共有 人打赏支持
城固如春
粉丝 11
博文 187
码字总数 25379
作品 0
杭州
程序员
私信 提问
Hibernate 映射xml中的属性类型

Hibernate的内置映射类型 1 JAVA基本类型(包括它们的包装类)和Hibernate映射类型 Hibernate Java类型 标准SQL类型 大小和取值范围 integer/int int/java.lang.Integer integer 4字节,-2^31...

长平狐
2013/01/06
1K
0
Java中的小数是怎么存储的?(转载学习)

Java中的小数使用double和float表示,小数属于浮点型(默认为double)。 对于float型的值,则要在数字后加f或F,如12.3F,它在机器中占32位,4个字节来存储,表示精度较低。double是64位。 那...

小海bug
2018/08/31
0
0
Java数据类型知多少?java入门学习

数据类型是每个编程语言必不可少的基础知识,也是必须要掌握的技能,很多人知识简单的进行理解,并没有很系统的进行知识的梳理,以下是对java语言的内置数据类型汇总:   Java语言有8种基本...

老男孩Linux培训
2018/06/27
0
0
Learn Java - Chapter 1 变量(Variables)-基本类型

java语言定义的变量包含一下四种类型 实例变量(Instance Variables),非静态变量,在Class中声明的field,未使用static声明; 类变量(Class Variables ),静态变量,在Class中使用stati...

Hassan
2015/06/01
0
0
Java Double相加出现的怪事

问题的提出: 编译运行下面这个程序会看到什么 [java] view plaincopy public class test { public static void main(String args[]) { System.out.println(0.05 + 0.01); System.out.print......

onedotdot
2017/11/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 白掌柜说了卖货不卖身

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @爱漫爱 :这是一场修行分享羽肿的单曲《Moony》 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :开不开心? 开心呀, 我又不爱睡懒觉…...

小小编辑
27分钟前
1
0
大数据教程(11.7)hadoop2.9.1平台上仓库工具hive1.2.2搭建

上一篇文章介绍了hive2.3.4的搭建,然而这个版本已经不能稳定的支持mapreduce程序。本篇博主将分享hive1.2.2工具搭建全过程。先说明:本节就直接在上一节的hadoop环境中搭建了! 一、下载apa...

em_aaron
32分钟前
0
0
开始看《JSP&Servlet学习笔记》

1:WEB应用简介。其中1.2.1对Web容器的工作流程写得不错 2:编写Servlet。搞清楚了Java的Web目录结构,以及Web.xml的一些配置作用。特别是讲了@WebServlet标签 3:请求与响应。更细致的讲了从...

max佩恩
今天
2
0
mysql分区功能详细介绍,以及实例

一,什么是数据库分区 前段时间写过一篇关于mysql分表的的文章,下面来说一下什么是数据库分区,以mysql为例。mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可...

吴伟祥
今天
2
0
SQL语句查询

1.1 排序 通过order by语句,可以将查询出的结果进行排序。放置在select语句的最后。 格式: SELECT * FROM 表名 ORDER BY 排序字段ASC|DESC; ASC 升序 (默认) DESC 降序 1.查询所有商品信息,...

stars永恒
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部