CPU有三种可能的浮点数处理方式
- Use float instructions if your CPU has a FPU. (fast)
- Have your compiler translate floating point arithmetic to integer arithmetic. (slow)
- Use float instructions and a CPU with no FPU. Your CPU will generate a exception (Reserved Instruction, Unimplemented Instruction or similar), and if your OS kernel includes a floating point emulator it will emulate those instructions (slowest).
那么如果没有FPU,最好将算法转移成定点来处理来提高速度,比如:
- 用整数来模拟浮点数
其实就是线性的映射,根据数据的动态范围把浮点映射到int8, int16或int32,
比如浮点数A,a=max(abs(A)),若要把A映射成-128~127的数,需要:
A_fix = A*(127 / a) ,即A=A_fix *a / 127;
如果B也是同样的浮点数,那么
A * B = A_fix* B_fix * a * b / (127 * 127) 就转化成一个定点运算。
注意A*(127 / a) 这一步会有精度损失,A_fix* B_fix * a * b / (127 * 127)这一步有可能溢出。
- 用定点小数来模拟浮点数
所谓定点小数,就是小数点固定的小数。可以参考这篇文章 Fixed Point Arithmetic on the ARM。可以用库libfixmath
这个库把浮点变换成Q16.16的定点小数来进行计算,并且可以变换回来。
对于Q16.16的数:
static const fix16_t fix16_one = 0x00010000;
static const fix16_t fix16_maximum = 0x7FFFFFFF;
static const fix16_t fix16_minimum = 0x80000000;
最大精度是1.525e-05, cout << fix16_to_float(0x00000001) <