C++中:无符号数相减结果也是无符号数。

4

在C++中,编译器会提醒我,从无符号数中减去另一个无符号数会得到无符号结果,因此调用abs()函数没有意义:

uint64_t a, b;
if (std::abs(a - b) > 10) {
    std::cout << "Divergence achieved!" << std::endl;
}

好的,我明白减法就是加法,我知道在我的情况下数字将小于2的63次方,因此我使用static_cast转换为int64_t。但调用abs的目的是避免编写以下内容:

if (a - b > 10 || b - a > 10) {
    std::cout << "Divergence achieved!" << std::endl;
}

有没有更通俗易懂的方式来完成这个操作?


3
建议的做法是一开始就使用有符号整数,参见C++核心指南 - sv90
3
@formerlyknownas_463035818 在无符号值上调用 abs 是没有意义的,因为它永远不会是负数。 - 1201ProgramAlarm
3
如果a是无符号整数,而b也是无符号整数,那么根据语言规则a-b的结果也将是无符号整数。 - 1201ProgramAlarm
1
@1201ProgramAlarm:除非它们都比“int”小,否则会发生提升并使它们有符号。这在这里使用“uint64_t”是极不可能发生的。 - Ben Voigt
1
可能是Does abs(unsigned long) make any sense?的重复问题。 - Christopher Oezbek
显示剩余8条评论
2个回答

5
您可以使用std::minmax,这样您就不必重复条件。这将为您提供最小值和最大值的引用,因此您始终可以以正确的方向进行减法运算。代码如下:
uint64_t a, b;
auto minmax = std::minmax(a,b);
if (minmax.second - minmax.first > 10) {
    std::cout << "Divergence achieved!" << std::endl;
}

这里会将10解释为有符号值吗?如果是的话,应该使用static_cast<uint64_t>(10)来防止将值隐式转换为负的有符号值而产生大的差异。 - paddy
1
@paddy 通常的算术转换将隐式地将其转换为 uint64_t - NathanOliver
@paddy 如果你想要更明确一些,你也可以使用 10ULL 作为无符号字面量。 - thc
1
在C++17中,std::apply(std::minus<>{}, std::minmax(a,b))auto[min,max]=std::minmax(a,b); 可以使用。我认为C++需要一种更简洁的方式来使用apply。 - Yakk - Adam Nevraumont
@Yakk-AdamNevraumont,你使用std::apply会导致min-max,这与所需的相反... - sv90
@sv90 是真的;错误是负数。 - Yakk - Adam Nevraumont

-4

计算机总是以二进制形式进行整数减法。有符号或无符号的赋值是一种指示编译器如何处理结果的指令。

例如:1-2(作为16位整数)将给出0xffff,对于有符号整数来说是-1,对于无符号整数来说是65535。

因此,如果您想要两个无符号整数之间的有符号差异,则

(int)(a - b);

希望这能有所帮助。


OP问如何做到这一点,而不是为什么会发生这种情况。 - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接