转载于:浮点数在计算机中存储方式
对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?
答:存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。浮点数存储算术标准IEEE 754。
浮点数存储分为3部分:
- 符号位(Sign): 0 0 0 为正, 1 1 1 为负数
- 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储(如:float指数范围 f r o m − 127 t o 128 from -127~~to~ 128 from−127 to 128,存储为 f r o m 0 t o 255 from~0~~to~~255 from 0 to 255)
- 尾数部分(Mantissa):…
R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:
8.25
∗
1
0
0
8.25*10^0
8.25∗100,而120.5可以表示为:
1.205
∗
1
0
2
1.205*10^2
1.205∗102。计算机根本以0-1方式存储,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01;120.5用二进制表示为:1110110.1(整数部分除二取余,小数部分乘二取整)。
用二进制的科学计数法表示1000.01可以表示为
1.00001
∗
2
3
1.00001*2^3
1.00001∗23; 1110110.1可以表示
为
1.1101101
∗
2
6
为1.1101101*2^6
为1.1101101∗26。
任何一个数都的科学计数法表示都为
1.
x
x
x
∗
2
n
1.xxx*2^n
1.xxx∗2n,二进制下用科学计数法表示,整数部分肯定是
1
1
1,可以将小数点前面的1省略,所以
23
b
i
t
23bit
23bit 的尾数部分,可以表示的精度却变成了
24
b
i
t
24bit
24bit 。那
24
b
i
t
24bit
24bit 能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以
4
b
i
t
4bit
4bit 能精确十进制中的1位小数点,
24
b
i
t
24bit
24bit 就能使
f
l
o
a
t
float
float 能精确到小数点后6位
指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127这样都变为整数了
例子:
而双精度浮点数的存储和单精度的存储大同小异,不同的是指数部分和尾数部分的位数。
疑惑:
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.25
2.25
2.25 的单精度存储方式,很简单
01000000100100000000000000000000
0 1000 0001 001 0000 0000 0000 0000 0000
01000000100100000000000000000000 , 而
2.25
2.25
2.25 的双精度表示为:
0100000000010010000000000000000000000000000000000000000000000000
0 100 0000 0001 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0100000000010010000000000000000000000000000000000000000000000000 ,这样
2.25
2.25
2.25 在进行强制转换的时候,数值是不会变的。
而我们再看看
2.2
2.2
2.2 呢,
2.2
2.2
2.2 用科学计数法表示应该为:将十进制的小数转换为二进制的小数的方法为将小数*2,取整数部分,所以
0.282
=
0.4
0.282=0.4
0.282=0.4 ,所以二进制小数第一位为
0.4
0.4
0.4 的整数部分
0
,
0.4
×
2
=
0.8
0,0.4×2=0.8
0,0.4×2=0.8 ,第二位为
0
,
0.8
∗
2
=
1.6
0,0.8*2=1.6
0,0.8∗2=1.6 ,第三位为
1
1
1,
0.6
×
2
=
1.2
0.6×2 = 1.2
0.6×2=1.2 ,第四位为
1
1
1 ,
0.2
∗
2
=
0.4
0.2*2=0.4
0.2∗2=0.4,第五位为
0
0
0 ,这样永远也不可能乘到=1.0,得到的二进制是一个无限循环的排列
00110011001100110011...
00110011001100110011...
00110011001100110011... , 对于单精度数据来说,尾数只能表示24bit的精度。
所以
1
/
2
n
1/2^n
1/2n的小数可以精确表示,且单双精度转换不会丢失或多小数。这主要由 十进制下小数部分 转换成 二进制的小数部分 的乘二取整的方法特性决定的。