我编写了以下测试代码来检查定点算术和位移。
void main(){
float x = 2;
float y = 3;
float z = 1;
unsigned int * px = (unsigned int *) (& x);
unsigned int * py = (unsigned int *) (& y);
unsigned int * pz = (unsigned int *) (& z);
*px <<= 1;
*py <<= 1;
*pz <<= 1;
*pz =*px + *py;
*px >>= 1;
*py >>= 1;
*pz >>= 1;
printf("%f %f %f\n",x,y,z);
}
结果是 2.000000 3.000000 0.000000
为什么最后一个数字是0?我期待看到一个5.000000 我想使用某种定点算法绕过在图像处理应用程序上使用浮点数。哪种是将浮点数组转换为整数的最佳/最简单/最有效的方法?以上“欺骗编译器”是一个强大的解决方法吗?有什么建议吗?
答案 0 :(得分:3)
如果您想使用固定点,请不要使用“float
”或“double
”类型,因为它们具有内部结构。浮标和双打有特定的符号位;一些用于指数的位,一些用于尾数(看一下彩色图像here);所以他们天生就是浮点。
您应该手动编程以整数类型存储数据,或使用某些定点库(或语言扩展)。
GCC中实现了浮点扩展的说明:http://gcc.gnu.org/onlinedocs/gcc/Fixed_002dPoint.html
C:http://www.eetimes.com/discussion/other/4024639/Fixed-point-math-in-C
有一些基于MACRO的定点手动实现答案 1 :(得分:2)
你正在做的事情是数字的残酷。
首先,为浮点变量赋值。它们的存储方式取决于系统,但通常使用IEEE 754 format。所以你的变量在内部看起来像
x = 2.0 = 1 * 2^1 : sign = 0, mantissa = 1, exponent = 1 -> 0 10000000 00000000000000000000000 = 0x40000000
y = 3.0 = 1.5 * 2^1 : sign = 0, mantissa = 1.5, exponent = 1 -> 0 10000000 10000000000000000000000 = 0x40400000
z = 1.0 = 1 * 2^0 : sign = 0, mantissa = 1, exponent = 0 -> 0 01111111 00000000000000000000000 = 0x3F800000
如果对这些数字进行一些位移操作,则会混淆符号,指数和尾数之间的边界,因此任何事情都可以,可能会发生。
在你的情况下:
后者通过添加-0.0和-1.1754943508222875e-38而失败,后者变为后者,即0x80800000,应该在&gt;&gt;再次增加1,3.0之后。我不知道为什么不是,可能是因为我在这里犯了错误。
留下的是你不能对浮子进行位移,期望得到可靠的结果。
我会考虑将它们转换为ARM上的整数或其他定点,然后按原样发送它们。
答案 2 :(得分:2)
您的编译器可能使用IEEE 754格式的float
s,在位方面,它看起来像这样:
SEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFF
^ bit 31 ^ bit 0
S
是符号位s = 1表示该数字为负数。
E
位是指数。有8个指数位给出范围0 - 255 但指数有偏差 - 你需要减去127得到真实指数。
F
位是小数部分,但是,你需要想象一个前面不可见的1,所以分数总是1.something,所有你看到的是二进制小数位。
数字2是1 x 2 1 = 1 x 2 128 - 127 所以编码为
01000000000000000000000000000000
因此,如果您使用位移来将其向右移动,那么
10000000000000000000000000000000
按照惯例,在IEEE754中为-0,所以不是将你的数字乘以2,而是你的班次为零。
数字3是[1 + 0.5] x 2 128 - 127
表示为
01000000010000000000000000000000
向左移动会给你
10000000100000000000000000000000
是-1 x 2 -126 或一些非常小的数字。
你可以对z做同样的事情,但是你可能会认为移动只是搞砸浮点数。
答案 3 :(得分:1)
固定点不会那样工作。你想做的是这样的:
void main(){
// initing 8bit fixed point numbers
unsigned int x = 2 << 8;
unsigned int y = 3 << 8;
unsigned int z = 1 << 8;
// adding two numbers
unsigned int a = x + y;
// multiplying two numbers with fixed point adjustment
unsigned int b = (x * y) >> 8;
// use numbers
printf("%d %d\n", a >> 8, b >> 8);
}