定点数和浮点数
定点数
我们用4个比特来表示0到9的整数,那么32比特就可以表示8个这样的整数。然后我们把最右边的2个0到9的整数当成小数部分,把左边的6个0到9的整数,当成整数部分。这样32比特就可表示0~999999.99的1亿个实数了。
浮点数
32比特表示单精度的浮点数就是float或者float32类型。64比特表示双精度的浮点数就是double或者float64类型。
单精度32比特可以分成三部分。
第一部分符号位s,用来表示正负数。在浮点数里,所有的浮点数都是有符号的。
第二部分指数位e,8比特可以表示2255。其中1254映射到-126~127。
第三部分有效数位f,23比特。
(-1)^s * 1.f * 2^e
这样的话,我们没有办法表示0。当e是0或255时有一下几种情况。
e | f | s | 浮点数 |
---|---|---|---|
0 | 0 | 0or1 | 0 |
0 | != 0 | 0or1 | 0.f |
255 | 0 | 0 | 无穷大 |
255 | 0 | 1 | 无穷小 |
255 | != 0 | 0or1 | NAN |
浮点数的二进制转化
十进制浮点数9.1如何表示二进制?
这里的9换算成二进制后是1001。
和整数部分十进制转二进制除以2比,小数部分转换成二进制是乘以2。然后看看是否超过1。如果超过1,就记下1,并把结果减去1,进一步循环操作。这里0.1变成无限循环的二进制,0.000110011,0011会无限循环下去。
然后我们把整数部分和小数部分拼接在一起,9.1十进制数就变成了1001.000110011…。
再用浮点数表示变成了1.001000110011… * 2^3。
兑换成s+f+e,f不是精确值。再转成十进制,精度就会丢失。
浮点数的加法和进度损失
先对齐,再计算
对齐指的是指数小的向大的对齐,对齐后,再将有效位相加。
加法过程中,其中指数位较小的数,需要在有效位进行右移,在右移的过程中,最右侧的有效位被丢弃。这会导致在加法发生前,就丢失精度。
kahan Summation算法
如何解决进度丢失,就是用这个算法。这个算法的简单思想是:在每次的计算过程中,都用一次减法,把当前加法计算中损失的精度记录下来,然后在后面的循环中,把这个精度损失放在要加的小数上,再做一次运算。