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

问题描述 投票:0回答:2

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

结果也必须是无符号整数(实际上独立于处理器,因为它在数学上只是 0 到 MAXINT 之间的数字)。

unsigned int a;
unsigned int b;

abs(a-b);

但这仅在 b<=a, otherwise a-b<0 and will then overflow, and taking

abs
稍后无济于事时才有效。

进行该计算的最简单且不会溢出的方法是什么?

(其实我想测试是否|a-b|

感谢评论中的答案,人们看到可以像使用案例区分一样完成一个简单的解决方案。

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

您可以使用简单的转换 如果

long long signed int
大于您平台上的
unsigned int
。它“可能”会是,但标准确实允许 int
long
long long
具有相同的大小。
(注:我特别使用了 
long long,因为在一些常见平台上 – 如 MSVC/Windows –
long int
int
大小相同,对于
unsigned
版本也是如此。)

这是一个使用

constexpr if

(编译时)检查的版本,如果转换不起作用,则使用更简单的测试优先解决方案:

#include <iostream>
#include <cmath>

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

如果 
long long signed int

类型足够大,可以容纳

unsigned int
类型的 所有可能值(如果它至少大一个字节的话),那么您只需要对以下操作数之一进行强制转换进行减法,因为在这种情况下,
unsigned int
的等级低于
long long int
,并且会在运算前提升为该类型。
    

c++ overflow unsigned unsigned-integer absolute-value
2个回答
1
投票

0
投票

您可以使用简单的转换 如果

long long signed int
大于您平台上的
unsigned int
。它“可能”会是,但标准确实允许 int
long
long long
具有相同的大小。
(注:我特别使用了 
long long,因为在一些常见平台上 – 如 MSVC/Windows –
long int
int
大小相同,对于
unsigned
版本也是如此。)

这是一个使用

constexpr if

(编译时)检查的版本,如果转换不起作用,则使用更简单的测试优先解决方案:

#include <iostream>
#include <cmath>

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

如果 
long long signed int

类型足够大,可以容纳

unsigned int
类型的 所有可能值(如果它至少大一个字节的话),那么您只需要对以下操作数之一进行强制转换进行减法,因为在这种情况下,
unsigned int
的等级低于
long long int
,并且会在运算前提升为该类型。
    

© www.soinside.com 2019 - 2024. All rights reserved.