float与double类型区别比较

原创 2012年07月31日 17:07:59

参考或转自http://topic.csdn.net/u/20090716/10/CE4A7037-3C0D-40AE-AF85-F702C78FCEA3.html

单精度浮点数在机内占4个字节,用32位二进制描述。

双精度浮点数在机内占8个字节,用64位二进制描述。

浮点数在机内用指数型式表示,分解为:数符,尾数,指数符,指数四部分。
数符占1位二进制,表示数的正负。
指数符占1位二进制,表示指数的正负。
尾数表示浮点数有效数字,0.xxxxxxx,但不存开头的0和点
指数存指数的有效数字。

指数占多少位,尾数占多少位,由计算机系统决定。
可能是数符加尾数占24位,指数符加指数占8位 -- float.
数符加尾数占48位,指数符加指数占16位 -- double.

知道了这四部分的占位,按二进制估计大小范围,再换算为十进制,就是你想知道的数值范围。

对编程人员来说,double 和 float 的区别是double精度高,有效数字16位,float精度7位。但double消耗内存是float的两倍,double的运算速度比float慢得多,C语言中数学函数名称double 和 float不同,不要写错,能用单精度时不要用双精度(以省内存,加快运算速度)。

=======================================================================================

类型 比特数 有效数字 数值范围 
float 32 6-7 -3.4*10(-38)~3.4*10(38) 
double 64 15-16 -1.7*10(-308)~1.7*10(308) 
long double 128 18-19 -1.2*10(-4932)~1.2*10(4932) 
简单来说,Float为单精度,内存中占4个字节,有效数位是7位(因为有正负,所以不是8位),在我的电脑且VC++6.0平台中默认显示是6位有效数字;double为双精度,占8个字节,有效数位是16位,但在我的电脑且VC++6.0平台中默认显示同样是6位有效数字(见我的double_float文件) 
还有,有个例子:在C和C++中,如下赋值语句 
float a=0.1; 
编译器报错:warning C4305: 'initializing' : truncation from 'const double ' to 'float ' 
原因: 
在C/C++中(也不知道是不是就在VC++中这样),上述语句等号右边0.1,我们以为它是个float,但是编译器却把它认为是个double(因为小数默认是double),所以要报这个warning,一般改成0.1f就没事了。 
本人通常的做法,经常使用double,而不喜欢使用float。

   C语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit, double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范 的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。

    无论是单精度还是双精度在存储中都分为三个部分:

  1. 符号位(Sign) : 0代表正,1代表为负
  2. 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
  3. 尾数部分(Mantissa):尾数部分

其中float的存储方式如下图所示:

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

而双精度的存储方式为:

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

     R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客,而120.5可以表示为:1.205*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客, 这些小学的知识就不用多说了吧。而我们傻蛋计算机根本不认识十进制的数据,他只认识0,1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数 法表示,8.25用二进制表示可表示为1000.01,我靠,不会连这都不会转换吧?那我估计要没辙了。120.5用二进制表示为:1110110.1用 二进制的科学计数法表示1000.01可以表示为1.0001*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客,1110110.1可以表示为1.1101101*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客,任何一个数都的科学计数法表示都为1.xxx*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客, 尾数部分就可以表示为xxxx,第一位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了 24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点, 24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以 指数部分的存储采用移位存储,存储的数据为元数据+127,下面就看看8.25和120.5在内存中真正的存储方式。

     首先看下8.25,用二进制的科学计数法表示为:1.0001*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

按照上面的存储方式,符号位为:0,表示为正,指数位为:3+127=130 ,位数部分为,故8.25的存储方式如下图所示:

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

而单精度浮点数120.5的存储方式如下图所示:

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

那么如果给出内存中一段数据,并且告诉你是单精度存储的话,你如何知道该数据的十进制数值呢?其实就是对上面的反推过程,比如给出如下内存 数据:0100001011101101000000000000,首先我们现将该数据分段,0 10000 0101 110 1101 0000 0000 0000 0000,在内存中的存储就为下图所示:

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

根据我们的计算方式,可以计算出,这样一组数据表示为:1.1101101*C++中,float double区别 - sunwenhua168 - sunwenhua168的博客=120.5

而双精度浮点数的存储和单精度的存储大同小异,不同的是指数部分和尾数部分的位数。所以这里不再详细的介绍双精度的存储方式了,只将120.5的最后存储方式图给出,大家可以仔细想想为何是这样子的

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

下面我就这个基础知识点来解决一个我们的一个疑惑,请看下面一段程序,注意观察输出结果

            float f = 2.2f;

            double d = (double)f;

            Console.WriteLine(d.ToString("0.0000000000000"));

            f = 2.25f;

            d = (double)f;

            Console.WriteLine(d.ToString("0.0000000000000"));

可能输出的结果让大家疑惑不解,单精度的2.2转换为双精度后,精确到小数点后13位后变为了2.2000000476837,而单精度的 2.25转换为双精度后,变为了2.2500000000000,为何2.2在转换后的数值更改了而2.25却没有更改呢?很奇怪吧?其实通过上面关于两 种存储结果的介绍,我们已经大概能找到答案。首先我们看看2.25的单精度存储方式,很简单 0 1000 0001 001 0000 0000 0000 0000 0000,而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存储为:

C++中,float double区别 - sunwenhua168 - sunwenhua168的博客

但是这样存储方式,换算成十进制的值,却不会是2.2的,应为十进制在转换为二进制的时候可能会不准确,如2.2,而double类型的数 据也存在同样的问题,所以在浮点数表示中会产生些许的误差,在单精度转换为双精度的时候,也会存在误差的问题,对于能够用二进制表示的十进制数据,如 2.25,这个误差就会不存在,所以会出现上面比较奇怪的输出结果。

参考:http://hi.baidu.com/kathyxiami/item/a2a9f28b9ff05d52e73d197c

相关文章推荐

JAVA中float与double的区别

float是单精度类型,精度是6位有效数字,取值范围是10的-38次方到10的38次方,float占用4个字节的存储空间 double是双精度类型,精度是15位有效数字,取值范围是10的-308次方到...

单精度浮点数(float)与双精度浮点数(double)的区别

【转载】 单精度浮点数(float)与双精度浮点数(double)的区别如下: (1)在内存中占有的字节数不同 •单精度浮点数在机内占4个字节 •双精度浮点数在机内占8个字节 (2)有效数字位...

深入理解C++浮点数(float、double)类型数据比较、相等判断

浮点数在内存中的存储机制和整型数不同,其有舍入误差,在计算机中用近似表示任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基...
  • cbNotes
  • cbNotes
  • 2014年08月29日 10:12
  • 15910

C++中,float double区别

类型               比特数      有效数字                          数值范围         float                  32     ...

Java变量以及内存分配(非常重要)

不知道是第几次看thinking in java了。不是的翻翻总有新的收获。堆栈静态存储区域一个由C/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)— 由编译器自动分配释放 ,存放函...
  • a675311
  • a675311
  • 2016年08月23日 19:26
  • 2519

JAVA如何把一个float四舍五入到小数点后2位,4位,或者其它指定位数.

怎么使float保留两位小数或多位小数 http://meryvn.blog.163.com/blog/static/36962664201173010402629/ 两种方法: impor...

java float和double 区别

来自百度知道:http://zhidao.baidu.com/link?url=O5UvP3PxCibnuhf6ovHleQsxTX-3ErdHuzXCkoxUvL_EomeF1y3nMTjb3ilp...

int,float,double之间不得不说的故事

这篇文章分析的挺好,只是有些代码不能验证的。 抱歉我用了一个这么“二”的题目,不过二点就二点吧,希望内容还不算太二。   其实学习过编程的同学,都对这三个东西再熟悉不过了。in...

Float和Double的讲解

java中Double和Float之间的转化及其double和float之间的区别

精确运算不能用float/double,用什么类型?

为什么不是2.2float f1=2.1;float f2=0.1;float f3=f1+f2;精确运算不能用float/double,用什么类型? 为什么说不能用 float 和 double 来...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:float与double类型区别比较
举报原因:
原因补充:

(最多只允许输入30个字)