C#浮点数的表示和基本运算

2019-12-30 14:40:36刘景俊

那么这些值是如何求出来的呢?

根据上面的约定,我们可以知道阶码P的最大值是11111110(这个值是254,因为255用于特殊的约定,那么对于可以精确表示的数来说,254就是最大的阶码了)。尾数的最大值是11111111111111111111111。

那么这个最大值就是:0 11111110 11111111111111111111111。

也就是 2(254-127) * (1.11111111111111111111111)2 = 2127 * (1+1-2-23) = 3.40282346638529E+38

从上面的双精度表示可以看出,两者是一致的。最小的数自然就是-3.40282346638529E+38。

对于最接近于0的数,根据IEEE754的约定,为了扩大对0值附近数据的表示能力,取阶码P = -126,尾数 M = (0.00000000000000000000001)2 。此时该数的二进制表示为:0 00000000 00000000000000000000001

也就是2-126 * 2-23 = 2-149 = 1.40129846432482E-45。这个数字和上面的Epsilon是一致的。

如果我们要精确表示最接近于0的数字,它应该是 0 00000001 00000000000000000000000

也就是:2-126 * (1+0)  =  1.17549435082229E-38。

3 浮点数的精度问题

浮点数以有限的32bit长度来反映无限的实数集合,因此大多数情况下都是一个近似值。同时,对于浮点数的运算还同时伴有误差扩散现象。特定精度下看似相等的两个浮点数可能并不相等,因为它们的最小有效位数不同。

由于浮点数可能无法精确近似于十进制数,如果使用十进制数,则使用浮点数的数学或比较运算可能不会产生相同的结果。

如果涉及浮点数,值可能不往返。值的往返是指,某个运算将原始浮点数转换为另一种格式,而反向运算又将转换后的格式转换回浮点数,且最终浮点数与原始浮点数相等。由于一个或多个最低有效位可能在转换中丢失或更改,往返可能会失败。

4 将浮点数表示为二进制

4.1 无小数的浮点数转换成二进制表示

首先,我们用一个不带小数的浮点数来说明如何将一个浮点数转换成二进制表示。假设要转换的数据是45678.0f。

在处理这种不带小数的浮点数时,直接将整数部分转化为二进制表示:

1011001001101110.0,这时要加上一位默认的1(这是因为按照浮点数规格化的要求,尾数必须化成 1.M的格式),

那么可以表示成:11011001001101110.0。

然后将小数点向左移,一直移到离最高位只有1位,也就是 1.1011001001101110,一共移动了16位,我们知道,左移位表示乘法,右移位表示除法。所以原数就等于这样:1.1011001001101110 * ( 216 )。现在尾数和指数都出来了。因为最高位的1是根据标准加上去的,只是为了满足规格化的要求,这时候需要把这个1去掉。尾数的二进制就变成了:1011001001101110。

最后在尾数的后面补0,一直到补够23位,就是:10110010011011100000000。