为什么在(uint32_t)((( - ( - )f)* 65536.0f))& 0xffff中实现与0xffff的按位与和?

时间:2016-10-16 04:26:24

标签: c bit-manipulation floating bitwise-and

这个问题与Section 7.4 of Beej's Guide to Network Programming中的代码示例有关。

这是代码示例。

uint32_t htonf(float f)
{
    uint32_t p;
    uint32_t sign;

    if (f < 0) { sign = 1; f = -f; }
    else { sign = 0; }

    p = ((((uint32_t)f)&0x7fff)<<16) | (sign<<31); // whole part and sign
    p |= (uint32_t)(((f - (int)f) * 65536.0f))&0xffff; // fraction

    return p;
}

为什么需要0xffff的按位AND来存储分数?

据我了解,f - (int) f始终是一个满足不等式0 <= f - (int) f < 1的数字。由于这个数字总是小于1,这个数字乘以65536总是小于65536.换句话说,这个数字在二进制表示中永远不会超过16位。

如果这个数字的长度永远不会超过16位,那么尝试用& 0xffff选择最低有效16位是什么意思。这对我来说似乎是一个多余的步骤。

你同意吗?或者您是否看到了& 0xffff这个功能正常工作所必需的场景?

1 个答案:

答案 0 :(得分:1)

& 0xffff是多余的。

甚至使用都值得怀疑。考虑以下。如果某些先前或未来的代码可能会创建some_float_expression < 0some_float_expression >= 0x10000,则使用& 0xffff截断表达式可能会导致错误的答案。以下就足够了。

(uint32_t)(some_float_expression);

IMO,代码还有其他问题:

  1. 没有范围错误检测。 @M.M

  2. 我希望转换为舍入到最接近的转换,而不是截断为0.0。

  3. 次要:if (f < 0)是检测-0.0f符号的错误测试。使用signbit()

  4. 不清楚为什么代码不像

    if (in range) 
      p = (uint32_t)(f*65536.0f) | (sign<<31);