快速检查两个 int32_t 之间的差异是 1 还是 0

mad*_*x60 5 c c++

一个直接的方法是

uint32_t diff = abs(num1 - num2);
bool isZeroOrOne = (diff == 0 || diff == 1);
Run Code Online (Sandbox Code Playgroud)

或者简单地检查所有可能的情况:

int32_t diff = num1 - num2;
bool isZeroOrOne = (diff == 0 || diff == 1 || diff == -1);
Run Code Online (Sandbox Code Playgroud)

有没有更优化的方法?

phu*_*clv 7

编译器已经知道像这样的范围比较的优化技术,不需要做任何花哨的事情,只需使用它

int32_t diff = uint32_t(num1) - uint32_t(num2);
bool isZeroOrOne = diff >= -1 && diff <= 1;
Run Code Online (Sandbox Code Playgroud)

(uint32_t)(num1 - num2 + 1) <= 2正如 Raymond Chen 评论的那样,编译器将优化为单个比较

unsigned需要进行强制转换以避免由于整数溢出而导致未定义的行为。-fwrapv或者在支持的编译器中使用

Godbolt 上的演示。正如你所看到的,编译器将下面的函数编译成完全相同的指令

#include <cstdint>

bool diff1(int32_t num1, int32_t num2)
{
    int32_t diff = uint32_t(num1) - uint32_t(num2);
    return diff >= -1 && diff <= 1;
}

bool diff2(int32_t num1, int32_t num2)
{
    int32_t diff = uint32_t(num1) - uint32_t(num2);
    return (uint32_t)(diff - (-1)) <= (1 - (-1));
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一种边缘情况,但 `diff1(INT32_MAX, INT32_MIN)` 返回 true... (6认同)
  • `uint32_t diff = (uint32_t)num1 - (uint32_t)num2; return diff+1 &lt;= 2;` 是一个更好的实现,可以避免未定义和实现定义的行为,但仍然会导致 `INT_MIN` 与 `INT_MAX` 大小写错误。 (3认同)
  • 这依赖于实现定义的行为,因为减法的结果可能超出“int32_t”的范围 (2认同)