- UBX中类似浮点数的8位和16位整形表示法:
8位是将高3位做指数,低5位做基数,范围是(0~31)乘以2的(0~7)次方。
16位是将高5位做指数,低11位做基数,范围是(0~2047)乘以2的(0~31)次方。
查阅IEEE754并没有上面的8位和16位的表示法,但是这种方法可以借鉴。
- IEEE754标准
图 4 浮点数计算公式
S是符号位。
E是指数位,如果是4字节的浮点数,则占8个比特位,其值E = 原始值+127。
M是纯小数。m = 1.M或者0.M,究竟是0还是1,由下图的隐含位决定。
图 5 浮点数的各种情况
图 6 IEEE754原文
例如:浮点数7.33转换成浮点数,先忽略符号位,目标是将该数转成这样的形式:
( 1.M或者0.M ) * (2E)
过程如下:
- 取整数位7,二进制0111b, 小数点左移2位,即 1.11b * 2^2。E = 2;M = 11b。
- 取小数部分0.33,使用乘以2取整数部分,直至余数全为0,或者全部占满M位数为止。4字节的浮点数,M的位数是23,减去整数占用的两个位,剩余21位,经过如下计算:
图 7 0.33的二进制计算
获得0.33的二进制数为:010101000111101011100b
补上前面整数的11,完整的23位M为:11010101000111101011100b
4字节指数E占8位,范围为(-126~127),其值是原始值+127,即2+127=129,二进制是1000 0001b。
由于是正数,符号位是0。将三部分合到一起即:
0100 0000 1110 1010 1000 1111 0101 1100 十六进制为 0X40EA8F5C
图 8 通过程序验证结果
按照该方法,8位或16位也可以用来表示浮点数。如果精度可以达到要求的话。
再重新看下UBX的RU1_3表示法:
二进制格式是eeeb bbbb 它表示值是bbbbb * 2^eee。
bbbbb 最大值是31,eee最大值是7。表示的范围是(0~3968)。比原先的0~255大了十多倍。
精度是~2^(value>>5),这个的意思通过下图可以看出来,我从小到大把每个值都打印了出来:
从图中可以看出到32 * 2^0的值精度为2^0;到32*2^1的值精度为2^1,以此类推最后的值精度为2^7 = 128。
这种方法有什么用?我想也许是有用的吧。这种表示方法,值越小精度越高,值越大精度越低,这多么像我们日常对精度的要求啊!比如机床要求是几丝的精度,身高是cm的精度就够了,而天文的误差可以更大。也就是越小的数字精度要求越高,越大的数字精度要求越低。
再重新看下浮点数表示法,它的精度是多少?
不考虑符号位s,e的取值范围(-126~127),m取值范围(0 ~ 1.11111111111111111111111b);
按照上面RU1_3表示法得出的规律:间隔值b * 2^e ,e值从最小值开始递增到最大,精度递增为2的e方。b值为11111b + 1b = 32。
浮点数的b值应该是:
1.11111111111111111111111b + 0.00000000000000000000001b = 2
精度变化为:间隔值2 * 2^e,e值从最小值-126开始递增到最大127,精度递增为2的e方。
代入一个数试试,比如123.123,这个值应该是在最接近于2^7,但精度显然不是2^6。
那么先固定2^e,让2^e是最大值,变化b,即 b * 2127 ,b就是M(1.xxxxx),
精度变化为:间隔值0.000000000000000000000012 * 2^127 = 2^104 (约2*10^31),b值从最小值开始,递增到最大1.11111111111111111111111b,精度递增为2^-23,即1.192 * 10^-7。
也就是说对现在的单精度浮点数来说,小于2*10^31的数,精度是1.192 * 10^-7,然后每间隔2*10^31,精度递加1.192 * 10^-7。