Vdsp(bf561)中的浮点运算(5):float范例暗示总结
副标题#e#
1.1 float的疑问
写一行很简朴的C代码:
float a = 1234.56;
用vdsp编译后的汇编代码为:
R0 = 20972 ( X ) ;
R0.H = 17562 ;
[ FP + 0x10 ] = R0 ;
有点看不懂,呵呵,R0的值转换为十六进制就是0x449A51EC。按照vdsp文档的说法,其单精度浮点数名目为:
浮点数计较公式:
将0x449A51EC转换为二进制:
0100 0100 1001 1010 0101 0001 1110 1100
可得:
Sign = 0
Mantissa = 001 1010 0101 0001 1110 1100
Exponent = 1000 1001
凭据公式
将Exponent转换为十进制,其值为137。
将Mantissa转换为十进制,其值为:
2-3 + 2-4 + 2-6 + 2-9 + 2 -11 + 2-15 + 2-16 + 2-17 + 2-18 + 2-20 + 2-21 =
0.125 + 0.0625 + 0.015625 + 0.001953125 + 0.00048828125 + 0.000030517578125 + 0.0000152587890625 + 0.00000762939453125 + 0.000003814697265625 + 0.00000095367431640625 + 0.000000476837158203125 = 0.205625057220458984375
代入浮点数计较公式:
(-1)0 + 1. 205625057220458984375 * 2 (137-127)
= 1234.56005859375
#p#副标题#e#
那么编译器又是如何将1234.56转换为0x449A51EC的呢?
首先转换整数部门,用2除,取余数,其功效为:
1234 / 2 = 617 ….. 0
617 / 2 = 308 …….1
308 / 2 = 154 …….0
154 / 2 = 77 ………0
77 / 2 = 38 ……….1
38 / 2 = 19 ……….0
19/ 2 = 9 ………….1
9 / 2 = 4………… .1
4/ 2 = 2 …………..0
2/2 = 1……………0
1/2 = 0……………1
即100 1101 0010,用16进制暗示则为:0x4d2。
再转换小数部门,用2乘,取整数位:
0.56 * 2 = 1.12取1
0.12 * 2 = 0.24取0
0.24 * 2 = 0.48取0
0.48 * 2 = 0.96取0
0.96 * 2 = 1.92取1
0.92 * 2 = 1.84取1
0.84 * 2 = 1.68取1
0.68 * 2 = 1.36取1
0.36 * 2 = 0.72取0
0.72 * 2 = 1.44取1
0.44 * 2 = 0.88取0
0.88 * 2 = 1.76取1
0.76 * 2 = 1.52取1
小数部门的值为0.1000 1111 0101 11
所以1234.56暗示成二进制数就是
100 1101 0010. 1000 1111 0101 11
由于浮点数暗示法的尾数部门以1开头,所以上面的这个数可以暗示为:
1.00 1101 0010 1000 1111 0101 11 * 210
从浮点数的暗示公式即可算出
Exponent = 127 + 10 = 137
而尾数部门则为
00 1101 0010 1000 1111 0101 11
因此整个数就是:
0 1000 1001 00 1101 0010 1000 1111 0101 11
标记位 指数 尾数
从整数的角度来看就是:
0100 0100 1001 1010 0101 0001 1110 1011
十六进制暗示为:
4 4 9 A 5 1 E B
奇怪得很,最后居然有毛病。岂非VDSP尚有什么构造不成?
1.2 FLT_MIN
FLT_MIN是在float.h中界说的一个常量,用以暗示单精度浮点数的最小值。
#define FLT_MIN 1.1754943508222875E-38F
那么这个值从何而来?
从浮点数的暗示可以知道,尾数一定是大于便是1的,要取最小值,只能将指数配置为最小值,由于浮点数划定将指数为0的环境暗示非凡的浮点数,因此指数只能取1,即
0 00000001 00000000000000000000000
标记位 指数 尾数
从16进制整数看它的值就是 0x00 80 00 00。
按照浮点数的计较公式可知这个值为:
1.0 * 2-126
= 1.1754943508222875079687365372222e-38
这个是计较器的计较功效。
1.3 FLT_MAX
FLT_MAX是在float.h中界说的一个常量,用以暗示单精度浮点数的最大值。
#define FLT_MAX 3.4028234663852886E+38F
那么这个值从何而来?
从浮点数的暗示可以知道,要取最大值,可以将指数和尾数都配置为最大值,由于尺度划定将指数全为1留做非凡暗示,故指数最大值为255,这个数即
0 11111110 11111111111111111111111
标记位 指数 尾数
从16进制整数看它的值就是 0x7f 7f ff ff。
按照浮点数的计较公式可知这个值为:
1. 9999997615814208984375 * 2(254-127)
= 3.4028234663852886E+38
这个是计较器的计较功效。
1.4 FLT_EPSILON
FLT_EPSILON是在float.h中界说的一个常量,用以暗示一个单精度浮点数的最小判别率,文档对此值的描写是:
A constant that represents the smallest value that may added to 1.0 and still result in a change of value (for example, FLT_EPSILON)
也就是加1后要能看得出变革!
FLT_EPSILON界说为:
#define FLT_EPSILON 1.1920928955078125E-07F
那么这个值从何而来?
先看1.0的浮点暗示:
0 01111111 00000000000000000000000
标记位 指数 尾数
从十六进制的角度看就是0x3f80 0000
要想把这个值加上一个足够小的值但仍然能看出变革,虽然就是把尾数直接加1,这个数即2-23,转换成十进制就是FLT_EPSILON的值。
下面是一个很有意思的问题:
float a = FLT_EPSILON;
这个时候a的值会是什么?
在VDSP下试了一下,a的值当作整数是:0x3400 0000,也就是:
0 01101000 00000000000000000000000
标记位 指数 尾数
即1.0 x 2(104-127) = 1.0 x 2-23
1.5 INF和NAN
IEEE754划定了单精度浮点数的范例:
#p#分页标题#e#
Type | Exponent | Fraction | Value |
NAN | 255 | Nonzero | Undefined |
Infinity | 255 | 0 | (–1)s Infinity |
Normal | 1 <= e <= 254 | Any | (–1)s (1.f22-0) 2 e–127 |
Zero | 0 | 0 | (–1)s Zero |
INF的暗示要求指数为255,尾数为0,即:
0 11111111 00000000000000000000000
标记位 指数 尾数
也就是0x7f80 0000。
在VDSP下可以用:
float a = 1.0 / 0.0;
来生成一个INF的数。
虽然,标记位也可以取负数,即:
1 11111111 00000000000000000000000
标记位 指数 尾数
也就是0xff80 0000。
在VDSP下可以用:
float a = -1.0 / 0.0;
来生成一个-INF的数。
上述两个INF都可以用isinf函数来检测它。
NAN的暗示要求指数为255,尾数不为0,即:
0 11111111 00000000000000000000001
标记位 指数 尾数(可取任意不为0的值)
也就是0x7f80 0001这样的数。
在VDSP下可以用:
float a = 0.0 / 0.0;
来生成一个NAN的数,不外这个时候它的值为0xffff ffff。
可以利用isnan函数来检测它。