如何计算两个无符号整数的绝对差?

How to calculate the absolute difference of two unsigned integers?

提问人:pas-calc 提问时间:10/22/2023 最后编辑:Adrian Molepas-calc 更新时间:10/22/2023 访问量:165

问:

在计算两个无符号整数之差的绝对值时,如何防止溢出?

结果也必须是一个无符号整数(实际上与处理器无关,因为它在数学上只是一个介于 0 和 MAXINT 之间的数字)。

unsigned int a;
unsigned int b;

abs(a-b);

但这只有在 b<=a 时才有效,否则 a-b<0 然后会溢出,以后服用也无济于事。abs

进行该计算的最简单、最安全的方法是什么?

(实际上我想测试 |a-b|<c 是否 其中 c 是某个常数。 因此,可以检查 a-bb 和 b-aa。

C++ 溢出 unsigned unsigned-integer absolute-value

评论

2赞 Eljay 10/22/2023
你能从较大的值中减去较小的值吗?
4赞 G.M. 10/22/2023
你或多或少已经回答了你自己的问题:(但不是在一行上)?if (a > b) return a - b; else return b - a;
1赞 Alexei Levenkov 10/22/2023
您能否更具体地说明“最简单”的要求?即为什么基本或不起作用?if? ... : ...
0赞 pas-calc 10/22/2023
@Eljay 先验地,我不知道哪个是较小的数字。
1赞 Peter 10/22/2023
怎么了?(a > b) ? (a - b) : (b - a)

答:

2赞 pas-calc 10/22/2023 #1

多亏了评论中的答案,人们看到一个简单的解决方案可以像使用大小写区分一样完成。

unsigned int uint_diff(unsigned int a, unsigned int b){
  if (a > b){
    return (a - b);
  }
  else {
    return (b - a);
  }
}

评论

0赞 Alexei Levenkov 10/22/2023
显然违背了 OP 的要求——“我本来会期待一些没有 if/else 但纯类型铸造的东西”。
1赞 Adrian Mole 10/22/2023
@AlexeiLevenkov 但这个回答者OP;)
0赞 Alexei Levenkov 10/22/2023
@AdrianMole我知道:)......有时 OP 需要提醒,答案实际上应该按要求回答问题,而不是为他们实际需要做的任何事情写答案......
0赞 Adrian Mole 10/22/2023 #2

如果平台上的 a 大于 an,则可以使用简单的强制转换。它可能会,但标准确实允许 ,并且大小相同。(注意:我特别使用 long long,因为在一些常见的平台(如 MSVC/Windows)上,long int 的大小与 int 相同,对于未签名的版本也是如此。long long signed intunsigned intintlonglong long

下面是一个使用(编译时)检查的版本,如果两个强制转换都不起作用,则回退到更简单的测试优先解决方案:constexpr if

#include <iostream>
#include <cmath>

unsigned int unsint_diff(unsigned int a, unsigned int b)
{
    if constexpr (sizeof(long int) > sizeof(unsigned int)) {
        return static_cast<unsigned int>
            (std::abs(static_cast<long signed int>(a) - static_cast<long signed int>(b)));
    }
    else if constexpr (sizeof(long long int) > sizeof(unsigned int)) {
        return static_cast<unsigned int>
            (std::abs(static_cast<long long signed int>(a) - static_cast<long long signed int>(b)));
    }
    else {
        return (a > b) ? a - b : b - a;
    }
}

int main()
{
    unsigned int i = 123456789u;
    unsigned int j = 987654321u;
    std::cout << unsint_diff(i, j) << "\n";
    std::cout << unsint_diff(j, i) << "\n";
    return 0;
}

请注意,您需要对减法的两个操作数进行强制转换,因为如果大小比较“成功”,那么调用将使用一个参数 - 这是模棱两可的,因此,代码格式不正确(这是不允许的,即使在实际不会使用的语句的正文中)。std::absunsigned intif constexpr