除以2的幂,导致浮动

Cod*_*rSS 3 c floating-point bit-manipulation

我发现自己需要计算16位无符号整数除以2的幂,这将导致32位浮点数(标准IEEE格式).这是在嵌入式系统上,并且例程被重复使用,所以我正在寻找更好的东西(float)x/(float)(1<<n).另外,C编译器非常有限(没有数学库,位字段,reinterpret_cast等).

Pau*_*l R 6

如果你不介意一点点,那么显而易见的方法是将整数转换为float,然后从指数位中减去n以实现除以2 ^ n:

y = (float)x;                          // convert to float
uint32_t yi = *(uint32_t *)&y);        // get float value as bits
uint32_t exponent = yi & 0x7f800000;   // extract exponent bits 30..23
exponent -= (n << 23);                 // subtract n from exponent
yi = yi & ~0x7f800000 | exponent;      // insert modified exponent back into bits 30..23
y = *(float *)&yi;                     // copy bits back to float
Run Code Online (Sandbox Code Playgroud)

请注意,对于x = 0,这会失败,因此您应该在转换前检查x> 0.

总成本是一个int-float转换加上一些整数按位/算术运算.如果使用union,则可以避免使用单独的int/float表示,只需直接在float上工作即可.


Eri*_*hil 5

使用ldexpf(x, -n)。这个函数是由 C 标准定义的,它可以完全满足您的要求,返回x \xe2\x80\xa22 -n,因此任何像样的编译器都会为此提供良好的代码。(这需要数学库的一部分或编译器将其优化为内联代码。)

\n\n

如果n在编译时已知,您也可以考虑x * (1.f/(1<<n)). 一个好的编译器会(1.f/(1<<n))在编译时进行计算,因此可执行代码将是两个操作:转换xfloat常量并乘以常量。ldexpf(x, -n)如果编译器没有优化的话,这可能比生成的代码更快ldexpf(x, -n)

\n