c++ - c++中的三向条件确定两个数字的符号等价性

标签 c++ performance algorithm optimization

我需要最有效的方法(在 cpu 周期内)来确定两个数字是否具有相同/不同的符号。但要注意的是,如果任一数字为零,我需要能够将其与具有相同/不同符号的数字区分开来(即。零被视为“第三个”符号)。以下代码与我需要的类似,但返回值可以是任何值,只要只有三个不同的返回值即可。

int foo(int x, int y) {
    if (x * y > 0) return 1;
    if (x * y < 0) return -1;
    return 0;
}

对于我的特定问题,值在 [-6, 6] 范围内并且 X 保证不为 0。我找到了一个解决方案来确定两个数字是否具有相同的符号,并对其进行修改以获得以下解决方案。

return y? (((x^y) >= 0)? 1 : -1) : 0;

应该有一些比使用乘法、分支、比较更快得到结果的位操作/比较。

最佳答案

怎么样:

int foo(int x,int y)
{
    // As suggested by Luther Blissett below in the comments.
    // Increased the size of the array to 16x16.
    // This allows for simpler optimization for the compiler
    // Also use +8 rather +6 in the hopes that compiler optimization will be easier
    // you never know (there may be some fancy trick.
    static int sign[16][16] = {
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1},
                { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1}
            };

    return sign[x+8][y+8];
}

这应该很快,因为没有会使处理器停止的分支。

使用 g++ -O3 -S:

__Z3fooii:
  pushl   %ebp
  movl    %esp, %ebp
  movl    8(%ebp), %eax
  movl    12(%ebp), %edx
  popl    %ebp
  sall    $4, %eax
  addl    %edx, %eax
  movl    _ZZ3fooiiE4sign+544(,%eax,4), %eax
  ret

关于c++ - c++中的三向条件确定两个数字的符号等价性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3297601/

相关文章:

c++ - Bash 脚本和 C++ 之间的持久 IPC

c++ - NSSet 与 unordered_set

c - 排序数组中的 "=="是否不比未排序数组快?

c - 如何向左旋转位并向右添加旋转位

c++ - Box2D静态库项目安装问题

c++ - 使用连接器 c++ 访问 MYSQL 数据库(如何添加到我的标准搜索目录的路径)

algorithm - 周期函数的渐近关系

algorithm - 算法能否分析函数的行为并判断另一个函数是否完全相同?

c++ - 将指针从一种基类型转换为另一种

java - 递归以获取数组中的所有变体总和