2012-06-19 50 views
1

有是应该使2个浮点值之间的比较,但速度比(在Cortex-A8的EG)在某些特定情况下经常比较C代码的解释

int isGreater(float* f1, float* f2) 
{ 
    int i1, i2, t1, t2; 

    i1 = *(int*)f1; // reading float as integer 
    i2 = *(int*)f2; // reading float as integer 

    t1 = i1 >> 31; 
    i1 = (i1^t1) + (t1 & 0x80000001); 

    t2 = i2 >> 31; 
    i2 = (i2^t2) + (t2 & 0x80000001); 

    return i1 > i2; 
} 

有人能解释下面的函数它是如何工作的?

+2

“但速度更快”。 - 比什么更快? –

+2

我想你可能会拉[这个有点](http://stackoverflow.com/questions/10381927/efficient-floating-point-comparison-cortex-a8)。 – Bart

+0

@Bart是的,我现在有一段时间在实际情况下尝试这些代码,但我仍然不明白它是如何工作的。 – Alex

回答

5

此代码利用浮点数的IEEE 754格式结构。该结构本身是专门为此类操作而设计的,以便快速进行比较操作。

每个单精度IEEE 754号有三个部分(为了从MSB到LSB):

  • 符号位
  • 指数部分(8个比特)
  • 有效数尾数的(23个比特)

f1大于f2如果:

  • f1为正,f2为负
  • f1f2都是积极的,但f1具有更大的指数比f2
  • f1f2均为正,并且具有相同的指数,但f1f2
  • 大尾数前两个相反f1f2是负数

如果浮点数是two's complement表示形式,则可以将两个浮点数作为整数进行比较。不幸的是,IEEE 754不使用二进制补码来表示负数,这就是为什么此代码执行转换以便能够将数字作为有符号整数进行比较。

这里是什么样的每一行代码确实一步步解说:

i1 = *(int*)f1; // reading float as integer 
i2 = *(int*)f2; // reading float as integer 

这一次使用的事实,在大多数32位系统sizeof(int) == sizeof(float)读取浮点数到正规签署整数变量。

t1 = i1 >> 31; 

这一个提取f1的符号位。如果f1为负,则其最高有效位将为1,因此i1将为负值。将它向右移动31位可以保留符号,因此如果i1为负数,则t1的所有位都将设置为1(等于-1)。如果f1为正,它的符号位将为0,最后t1将等于0

i1 = (i1^t1) + (t1 & 0x80000001); 

如果符号位为1这条线将执行转换为二进制补码表示,如果f1为阴性。

这里是它如何工作的:如果f1呈阳性,那么t10(i1^t1)也只是i1(t1 & 0x80000001)0并最终i1将只保留其原始值。如果f1为负数,则t1将所有位设置为1,并且RHS上的第一个表达式将是i1的位反转,第二个表达式将等于0x80000001。这种方式i1将被转换为其位反转,并且将添加1。但是这将导致一个正数,因为MSB将被清除,这就是为什么0x80000000也被添加来保持数字为负。

t2 = i2 >> 31; 
i2 = (i2^t2) + (t2 & 0x80000001); 

f2执行与上述相同的操作。

return i1 > i2; 

只是比较两个结果签署整数。大多数CPU都有专用指令来执行硬件中的带符号比较。