计算浮点中点

时间:2017-04-17 07:45:32

标签: bit-manipulation ieee-754

给定两个浮点数(IEEE单精度或双精度),我想找到它们之间的数字,但不是(x + y)/ 2意义上的数字,而是实际可表示的号。

如果x和y都是正数,则以下工作

float ieeeMidpoint(float x, float y)
{
    assert(x >= 0  && y >= 0);
    int xi = *(int*)&x;
    int yi = *(int*)&y;
    int zi = (xi+yi)/2;
    return *(float*)&zi;
}

这样做的原因是,在进行重新解释演员表时,正的ieee浮点数(包括次正规和无穷大)会保持其顺序。 (对于80位扩展格式,情况并非如此,但无论如何我都不需要这样做。)

现在我正在寻找一种优雅的方式来做同样的事情,包括一个或两个数字都是负数的情况。当然很容易用一堆if,但我想知道是否有一些不错的位魔法,最好没有任何分支。

1 个答案:

答案 0 :(得分:0)

自己想出来。在进行重新解释转换时,负数的顺序会反转,因此这是唯一需要修复的内容。这个版本比我希望的要长,但它只是一点点改组,所以它应该很快。

float ieeeMidpoint(float x, float y)
{
    // check for NaN's (Note that subnormals and infinity work fine)
    assert(x ==x && y == y);

    // re-interpreting cast
    int xi = *(int*)&x;
    int yi = *(int*)&y;

    // reverse negative numbers
    // (would look cleaner with an 'if', but I like not branching)
    xi = xi ^ ((xi >> 31) & 0x3FFFFFFF);
    yi = yi ^ ((yi >> 31) & 0x3FFFFFFF);

    // compute average of xi,yi (overflow-safe)
    int zi = (xi >> 1) + (yi >> 1) + (xi & 1);

    // reverse negative numbers back
    zi = zi ^ ((zi >> 31) & 0x3FFFFFFF);

    // re-interpreting back to float
    return *(float*)&zi;
}
相关问题