文档章节

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

城固如春
 城固如春
发布于 2017/09/09 15:14
字数 1084
阅读 4
收藏 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

共有 人打赏支持
城固如春
粉丝 9
博文 195
码字总数 22355
作品 0
杭州
程序员
Java中的小数是怎么存储的?(转载学习)

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

小海bug
08/31
0
0
Learn Java - Chapter 1 变量(Variables)-基本类型

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

Hassan
2015/06/01
0
0
Java数据类型知多少?java入门学习

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

老男孩Linux培训
06/27
0
0
深入理解JAVA虚拟机学习笔记13——字节码指令2(运算指令)

本篇继续字节码指令的学习,开始之前,先巩固一下基础知识,Java中基本数据类型的范围。 1. 整型: 1.1 byte:数据类型是8位、有符号的整数,取值范围-128~127; 1.2 short: 数据类型是 16...

徐可心
06/20
0
0
Java小白进阶笔记(2)-变量和数据类型

1.Java有多少种数据类型,数据类型的分类? 两种数据类型: 基本数据类型 引用数据类型 除了八种基本数据类型,其他的都是引用数据类型。 2.Java的工作机制? Java程序的源代码(.java)编译...

阿里云云栖社区
05/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux运维人员必会运维工具

linux运维人员必会开源运维工具体系 说明:不同的技术人员,不同的阶段确定知识边界非常重要,否则,就像马拉车,不知道终点在哪,累死也达不到目标。例如拿8K要学多少,拿15K要学多少。一个...

寰宇01
20分钟前
2
0
10大PHP比特币开源项目

如果你是一个Phper,如果你希望学习区块链,那么本文列出的 10个开源的Php比特币项目,将有助于你了解在自己的应用中 如何加入对比特币的支持。 如果你希望快速掌握使用Php对接比特币钱包的方...

汇智网教程
41分钟前
1
0
springclould feign客户端添加全局参数

用springclould feign作为调用服务的客户端,一般来说参数可以写在feignclient的方法参数里 有时需要所有feign请求都统一添加一些参数,例如token用于鉴权等,可以这样做: 添加一个配置类,...

canneljls
42分钟前
1
0
win32截屏并rgb24转yuv420

//最终f的内存布局为BGRA格式,需要保证buf长度足够(>w*h*4)void ScreenCap(void* buf, int w, int h){ HWND hDesk = GetDesktopWindow(); HDC hScreen = GetDC(hDesk); ......

styleman
今天
1
0
php输出mysql取出的中文为??的问题

解决方法: @ $db=new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_DB); $db->query("set names utf8");//添加此语句,可以解决问题...

Aomo
今天
1
2

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部