计算一下浮点数(初步了解一下浮点数)
计算一下浮点数(初步了解一下浮点数)NaN表示not a number : 当阶码全为1,尾数不全为0,此时为NaN;这里又涉及到 quiet NaN和signaling NaN;如果尾数的首位是1,那么就是quiet NaN;如果尾数的首位是0,其余尾数有不为0,那么就是signaling NaN。这是 大多数处理器,包括Intel与AMD的x86系列、Motorola68000系列、AIMPowerPC系列、ARM系列、SunSPARC系列,采取的标准。这个标准被IEEE754采纳。其中,阶码是由原码加上移码构成,所谓移码(exponential bias),值为2^(N-1)-1,如单精度时,移码为2^7-1=128单精度浮点数:1位符号位,8位阶码,23位尾数,共32位,占4个字节双精度浮点数:1位符号位,11位阶码,52位尾数,共64位,占8个字节长双精度浮点数:1位符号位,15位阶码,64位尾数,共80位,占10
写一篇逻辑严密的文章,涉及到的东西太多,实在很困难,所以某些方面就不深究下去,仅做一个知识点的粗浅归纳。
关于浮点数
IEEE754标准规定:
浮点数的构成:1位符号位 N位阶码 M位尾数(原码表示)
单精度浮点数:1位符号位,8位阶码,23位尾数,共32位,占4个字节
双精度浮点数:1位符号位,11位阶码,52位尾数,共64位,占8个字节
长双精度浮点数:1位符号位,15位阶码,64位尾数,共80位,占10个字节
其中,阶码是由原码加上移码构成,所谓移码(exponential bias),值为2^(N-1)-1,如单精度时,移码为2^7-1=128
NaN表示not a number : 当阶码全为1,尾数不全为0,此时为NaN;这里又涉及到 quiet NaN和signaling NaN;如果尾数的首位是1,那么就是quiet NaN;如果尾数的首位是0,其余尾数有不为0,那么就是signaling NaN。这是 大多数处理器,包括Intel与AMD的x86系列、Motorola68000系列、AIMPowerPC系列、ARM系列、SunSPARC系列,采取的标准。这个标准被IEEE754采纳。
而 PA-RISC与MIPS处理器,采取了首位为'is_signaling'标记位,恰与上述标准相反。
说明我的猜测是正确的。
几个例子
float x11=3.00000011f 和 float x22=3.00000012f是不相等的;
float x11=3.00000011f 和 float x22=3.00000010f是相等的;
请问,float x11=100.00000022f和float x22=100.00000011f是否相等。
100,划分为二进制是1100100,归一化后,它的100100归入了尾数中,导致归一化之前的尾数中的第22 23位都被分离了出去,原来的位17变成了现在的位23,并且原来的位18也是0,即现在的位24是0,所以24位及其后面的都被舍去。即x11和x22是相同的。
也就是说:当一个浮点数,整数部分的值很大时,这会占据小数部分的有效位。
另外,也可以这样理解:
x11=100.00000022f,归一化就是1.00 00000022f ;
x22=100.00000011f,归一化就是1.00 00000011f;
从小数部分数7位,发现以上都是一样的,所以x11和x22是相等的;
这就是规律。
即:先把数归一化,得到首尾是1的数,再判断它的小数部分,7位有效位,同时判断第8位的值是否超过机器ε的一半。若有,则有进位。否则,舍去。
对于double,双精度浮点数:
1位符号位,11位阶码,52位尾数,共64位。
那么它的机器ε就是:2^(-52),即0.000000000000000222
即双精度浮点数的有效位是小数点后16位。
下面,实际的计算一下,3.1415这个浮点数当类型是双精度时,在内存中的表示。
3换算为二进制就是11
0.1415换算为二进制就是0010 0100 0011 1001 0101 1000 0001 0000 0110 0010 0100 1101 1101{0...}
所以3.1415的二进制表示就是:
11. 0010 0100 0011 1001 0101 1000 0001 0000 0110 0010 0100 1101 1101{0...}
归一化为:
1.1 0010 0100 0011 1001 0101 1000 0001 0000 0110 0010 0100 1101 1101{0...}
因为归一化了,将整数部分的1划入了尾数,所以此时尾数是:
1 0010 0100 0011 1001 0101 1000 0001 0000 0110 0010 0100 1101 110{10...}
第53位是1,进1,得到:
1.1 0010 0100 0011 1001 0101 1000 0001 0000 0110 0010 0100 1101 111
尾数换算为16进制就是:921CAC083126F
阶码的原码是1,即2^1,因为这个是双精度浮点数,可知它的移码是2^(11-1)-1,即:
十进制数1023,换算为16进制数是3FF,加上阶1,得到400
所以3.1415,用双精度表示就是:
0 {11-1111-1111} {1 0010 0100 0011 1001 0101 1000 0001 0000 0110 0010 0100 1101 111}
从后往前,4bit一组,构成16进制,表示为:
0x400921CAC083126F
下面,用软件来验证3.1415的双精度浮点数,在内存中的值是不是 0x400921CAC083126F
unsigned long long a=0x0;
double b=3.1415;
a=*((unsigned long long *)(&b));
意思是:取得变量b的地址,将这个地址的类型转换为unsigned long long *,然后取得这个地址的内容,送给a
debug中断,查看&b的值是0x0012FEA8 从这个地址开始的8个字节的内存值是:
我的电脑是Intel处理器,数据在内存中是以小尾形式保存的,即数据的高字节保存在内存的高地址处;数据的低字节保存在内存的低地址处。
因此,从地址0x0012FEA8开始的8个字节,组成的数据是0x400921CAC083126F