将浮点宏与int *一起切换 - 它有什么作用?

时间:2016-07-14 11:03:02

标签: c++ opencv casting ieee-754 feature-extraction

我试图理解OpenCV中的AKAZE功能实现,当我遇到以下宏时感到困惑:

/* IEEE754 constants and macros */
#define  CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0))

它以下列方式用于MLDB二进制比较(我删除了代码中所有不相关的部分):

void MLDB_Binary_Comparisons(float* values)
{
    int* ivalues = (int*)values;
    for (int i = 0; i < count * chan; i++)
        ivalues[i] = CV_TOGGLE_FLT(ivalues[i]);

    /* ... The ivalues are then compared to each other using the > operator */
}

有谁知道这里发生了什么?将浮点*强制转换为int *是否真的安全,宏实际上做了什么?

提前致谢!

1 个答案:

答案 0 :(得分:2)

本质上,它以非可移植的方式对浮点数据进行一些二进制操作:显然有关于intfloat的相对大小的假设以及它们的表示。我认为如果 int是32位二进制补码整数,float是IEEE 32位浮点值,那么它可以让你比较浮点数值只使用整数运算。

更详细......

int* ivalues = (int*)values;

这只是给我们一个用于遍历浮点值的指针。它们被解释为ints,而非已转换int - 换句话说,没有理由认为float与值1.0将映射到int 1的值。因此,您可以做的主要是按位操作或依赖于理解用于float的二进制格式的特定操作。

看宏......

#define  CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0))

x(记住,只是其中一些代表浮点值的位,但我们只是将它看作一个位模式)与0进行异或运算(没有效果)或0x7fffffff(反转低位31位)。决定做什么是基于x是否小于零。

我认为这个宏是基于int是32位二进制补码表示的假设。这意味着如果设置了最高位,则x < 0为真。带0x7fffffff的XOR将反转其他位。这意味着-1,最正的负数,从0xffffffff更改为0x8000000,这是最负的负数(-2147483648),同样{{1变成0x8000000。在此之后使用0xffffffff来比较两个负数时,这意味着更多负面数字现在是更多正面数字,而“更大比“将采取分支。比较两个正数是不变的,并且将正数与负数进行比较,正数正如您所期望的那样,仍然总是更大。

这使您可以仅使用整数运算对>进行比较。这是因为IEEE格式的float存储负数的方式与2的补码完全不同:符号位实际上只是一个值为正或负的标志,其余的位存储幅度数量。应用float后,您没有可以直接使用的值,但它们的排序方式与原始CV_TOGGLE_FLT(x)值相同。