*(2^n )的形式)“^”表示幂,2 ^
n表示2的n次方)。 对于纯小数d,n的计算公式如下:
n=1log2(d; //用纯小数求出的n一定是负数
进而在d/(2^n )下
得到标准化的小数。 其次是从十进制到二进制的转换问题。 为了便于理解,我们先来看看十进制的纯小数是如何表示的。 假设有纯小数d,该小数点以下的各位数字依次形成集合:
{k1,k2,k3,kn}
d可以表示为:
d=K1/(10^1) k2/(10 ^2) k3/(10 ^3) ) ) ) ) ) ) ) ) ) ) ) 652 .
kn/(10^n )。
展开为二进制时,纯小数表示形式如下:
d=B1/(2^1) B2/(2^2) B3/)2^3) . bn /
(2 ^ n ) ) ) )。
问题是如何求出b1、b2、b3、…、bn。 算法说明很复杂,还是用数字说吧。 声明,1/(2^
n )这个数比较特殊,我叫它阶级值。
例如,0.456、第1位、0.456小于灰度值0.5,所以为0; 第二位,0.456大于灰度值0.25,该位为1,0.45减去0.25将0.206进位到下一位; 第三位,0.206大于灰度值0.125,该比特为1,0.206减去0.125,0.081进入下一个比特; 第四位,0.081大于0.0625,1,0.081减去0.0625,0.0185进入下一位; 第五名0.0185小于0.03125
最后按位顺序组合计算得到的足够数量的1和0,可以得到比较准确的二进制表示的纯粹小数。 同时,也会产生精度问题。 许多数不能在有限的n内完全准确地表示。 我们为了更准确地表示这个数,只能利用更大的n值。 因此,在很多领域程序员喜欢用double而不是float。
浮点存储器结构。 用带位域的结构体记述如下。
直截了当的浮体
{
bool bSign : 1; //符号表示正负,1位
char cExponent : 8; //指数,8位
unsigned long ulMantissa : 23; //尾数,23位
(;
符号自不必说,1表示负,0表示正
指数以2为底,范围从-128开始
127、实际数据中的指数为原指数加127,超过127的从-128开始计算
,其行为和X86架构的CPU处理加减法的溢出是一样的。比如:127 + 2 = -127;-127 - 2 = 127
尾数都省去了第1位的1,所以在还原时要先在第一位加上1。它可能包含整数和纯小数两部分,也可能只包含其中一部分,视数字大小而定。对于带有整数部分的浮点数,其整数的表示法有两种,当整数大于十进制的16777215时使用的是科学计数法,如果小于或等于则直接采用一般的二进制表示法。科学计数法和小数的表示法是一样的。
小数部分则是直接使用科学计数法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n
)。拆开来看。
0 00000000 0000000000000000000000
符号位 指数位 尾数位
定点数与浮点数的比较 数值的表示范围 :浮点表示法所能表示的数值范围将远远大于定点表示法 。
精度
:对于字长相同的定点数与浮点数来说,浮点数虽然扩大了数的表示范围,但这是以降低精度为代价的,也就是数轴上各点的排列更稀疏了
。
数的运算 :浮点运算要比定点运算复杂 。
溢出处理
:定点运算时,当运算结果超出数的表示范围,就发生溢出;而在浮点运算时,运算结果超出尾数的表示范围却并不一定溢出,只有当阶码也超出所能表示的范围时,才发生溢出。