float介绍 float left

1.数据存储

float的指数位有8位,而double的指数位有11位,分布如下:

float:

1bit(符号位)

8bits(指数位)

23bits(尾数位)

double:

1bit(符号位)

11bits(指数位)

52bits(尾数位)

在数学中,特别是在计算机相关的数字(浮点数)问题的表述中,有一个基本表达法:

valueoffloating-point= significandx base^exponent,withsign
即:数值 = 尾数 ×底数^指数,(附加正负号)

其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEER32.24,而double遵从的是R64.53。R32. 24和R64.53的存储方式都是用科学计数法来存储数据的。

指数部分的存储采用移位存储,存储的数据为元数据+127,下面就看看8.25和120.5在内存中真正的存储方式。

8.25用十进制的科学计数法表示就为:8.25*10^0,而120.5可以表示为:1.205*10^2。而在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,120.5用二进制表示为:1110110.1用二进制的科学计数法表示1000.01可以表示为1.0001*2^3,1110110.1可以表示为1.1101101*2^6。

首先看下8.25,二进制:1.0001*2^3

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

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

对于一个小数其默认类型为double型,如果需要指定为float型,需要在小数后面添加F或f后缀。

如floata=0.5f;

2.范围

范围主要是来讨论最大最小值。

float和double的范围是由指数的位数来决定的。对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127~+128了。

即float的指数范围为-127 ~+128(+-2^7),

而double的指数范围为-1023 ~ +1024 (+-2^10),

并且指数位是按补码的形式来划分的。


其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。

float的范围为-2^128 ~+2^128 也即-3.40E+38~+3.40E+38;

double的范围为-2^1024~+2^1024,也即-1.79E+308~+1.79E+308。

类型名

占内存字节数(B)

值的范围

float

4

-3.40E+38~+3.40E+38

double

8

-1.79E+308~+1.79E+308

longdouble

10

-3.4E+4932~+1.1E+4932



其他特殊表示

111111111尾数的23位不全为0:表示不是数值
11111111100000000000000000000000:表示负无穷大.比最小负数还小的数都视为负无穷大.
11111111011111111111111111111111:表示最小的负数,即-2^128=-3.4*10^38
10000000100000000000000000000000:表示最大的负数,即-2^(-126)=-1.18*10^(-38)
00000000000000000000000000000000:表示0
00000000100000000000000000000000:表示最小的正数,即2^(-126)=1.18*10^(-38)
01111111011111111111111111111111:表示最大的正数,即2^(128)=3.4*10^(38)
01111111100000000000000000000000:表示正无穷大,比最大正数还大的数都视为正无穷大.
011111111尾数的23位不全为0:表示不是数值

当指数部分和小数部分全为0时,表示0值,有+0和-0之分(符号位决定),0x00000000表示正0,0x80000000表示负0.
指数部分全1,小数部分全0时,表示无穷大,有正无穷和负无穷,0x7f800000表示正无穷,0xff800000表示负无穷.

故,float型数据的表示范围包括:
负无穷大;-3.4*10^38<x<-1.175*10^(-38);0;1.175*10^(-38)<x<3.4*10^38;正无穷大.

3.精度

精度主要是来讨论数据通过科学计数法表达后,小数点后数据位数。

float和double的精度是由尾数的位数来决定的。任何一个数的科学计数法表示都为1.xxx*2^n,尾数部分就可以表示为xxxx,第一位都是1,可以将小数点前面的1省略,故不能对精度造成影响。

那么对于尾数

float:2^23=8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;

double:2^52=4503599627370496,一共16位,同理,double的精度为15~16位。

或,

log(2^23)=6.xx,取整即6;
float介绍 float left
log(2^53)=15.95,取整即15;
log(2^65)=19.57,取整即19。

4.问题

inti=Int32.MaxValue;

floatf=i;

intj=(int)f;

boolb=i==j;

这里的b,是false。刚才这个操作,如果我们把float换成long,第一次进行隐式转换,第二次进行强制转换,结果将会是true。乍一看,float.MaxValue是比int.MaxValue大了不知道多少倍的,然而这个隐式转换中,却造成了数据丢失。int.MaxValue,这个值等于2^31-1,写成二进制补码形式就是01111…(31个1),这个数,在表示成float计数的科学计数法的时候,将会写成+0.1111…(23个1)*2^31,对于那31个1,里面的最后8个,被float抛弃了,因此,再将这个float强制转换回int的时候,对应的int的二进制补码表示已经变成了0111…(23个1)00000000,这个数与最初的那个int相差了255,所以造成了不相等。

那么提出另一个问题,什么样的int变成float再变回来,和从前的值相等呢?这个问题其实完全出在那23位float的数据位上了。对于一个int,把它写成二进制形式之后,成为了个一32个长度的0、1的排列,对于这个排列,只要第一个1与最后一个1之前的间距,不超过23,那么它转换成float再转换回来,两个值就会相等。这个问题是与大小无关的,而且这个集合在int这个全集下并不连续。

floatf=2.2f;

doubled=(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的单精度存储方式,01000000100100000000000000000000,而2.25的双精度表示为:0100000000010010000000000000000000000000000000000000000000000000,这样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存储为

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

类似地,

doubled=0.6;

floatf=(float)d;

doubled2=f;

boolb=d==d2;

这里的b,也是false。由于float保存23位,而double保存52位,就造成了double转化成float的时候,丢失掉了一定的数据,非再转换回去的时候,那些丢掉的值被补成了0,因此这个后来的double和从前的double值已经不再一样了。

那么什么样的十进制小数,表示成二进制不是无限小数呢?对于所有的最后一位以5结尾的十进制有限小数,都可以化成二进制的有限小数。

浮点数与十进制之间的互相转换体现在存在内存里的数明显实际与0.6不等,但是无论哪种语言,都能够在Debug以及输入的时候,将它正确的显示成0.6提供给用户(程序员),最好的例子就是double和ToString方法,如果我写doubled=0.59999999999999999999999999999,d.ToString()给我的是0.6。

最后,一个有意思有问题,刚才说过0.6表示成为二进制小数之后,是0.1001并且以1001为循环节的无限循环小数,那么在我们将它存成浮点数的时候,一定会在某个位置将它截断(比如float的23位和double的52位),那么真正存在内存里的这个二进制数,转化回十进制,到底是比原先的十进制数大呢,还是小呢?答案是Itdepends。人计算十进制的时候,是四舍五入,计算机再计算二进制小数也挺简单,就是0舍1入。对于float,要截断成为23位,假如卡在24位上的是1,那么就会造成进位,这样的话,存起来的值就比真正的十进制值大了,如果是0,就舍去,那么存起来的值就比真正的十进制值小了。因此,这可以合理的解释一个问题,就是0.6d转换成float再转换回double,它的值是0.60000002384185791,这个值是比0.6大的,原因就是0.6的二进制科学计数法表示,第24位是1,造成了进位。

  

爱华网本文地址 » http://www.413yy.cn/a/25101016/317041.html

更多阅读

2013-2014好看的韩剧介绍 好看的韩剧排行榜2013

2013-2014好看的韩剧介绍——简介有很多朋友都找不到喜欢的电视剧看,在这里为大家推荐几部个人觉得很好看的韩国电视剧,看时间长了韩语会有进步哦~~2013-2014好看的韩剧介绍——方法/步骤2013-2014好看的韩剧介绍 1、第一部就是之前

百战天下聊天系统介绍 百战天下进阶数据

百战天下聊天系统介绍——简介百战天下聊天系统介绍百战天下聊天系统介绍——工具/原料浏览器百战天下聊天系统介绍——方法/步骤百战天下聊天系统介绍 1、一、发送聊天  聊天框位于游戏左下方,玩家在输入框中输入文字,并可以选择

仓颉输入法简单介绍和学习

? ?输入法的确实可以给商家带来不错的效益,要不然怎么会有这么多人开发设计这么多不同的输入法那.今天给大家介绍一个很早的输入法:仓颉输入法!仓颉输入法是香港等以繁体字为主的地区常用的输入法.与五笔的编码有所不同,更适合来

声明:《float介绍 float left》为网友搞笑先生分享!如侵犯到您的合法权益请联系我们删除