"unsigned long long int"数据类型的std::abs函数

7
为什么会出现这个错误
 C2668: 'abs' : ambiguous call to overloaded function

对于像这样的简单代码

#include <iostream>
#include <cmath>
int main()
{
  unsigned long long int a = 10000000000000;
  unsigned long long int b = 20000000000000;
  std::cout << std::abs(a-b) << "\n";   // ERROR
  return 0;
}

移除std::后错误仍然存在。但是,如果我使用较小值的int数据类型,则没有问题。

传统的解决方案是手动检查。

std::cout << (a<b) ? (b-a) : (a-b) << "\n";

那是唯一的解决方案吗?

5
为什么要对无符号类型执行 abs 操作?(这不是一个修辞问题) - Mario
2
@Mario,他们希望对两个无符号值的差异进行绝对值运算。 - juanchopanza
无符号类型不会发生溢出吗?a-b的结果不是-10000000000000,而是std::numeric_limits<unsigned long long>::max()-10000000000000(仍为unsigned long long)。 - Pixelchemist
注意 << 的优先级高于 ?:,所以记得加括号!http://en.cppreference.com/w/cpp/language/operator_precedence - BoBTFish
4个回答

11

检查似乎是唯一真正好的解决方案。其他替代方案需要比你的类型更大,以及非标准扩展来使用它。

如果您的范围适合,可以选择将解决方案转换为带符号的long long。尤其是如果实现只放置在一个仅执行此操作的函数中,我强烈建议使用这种方式。


5
您正在包含<cmath>,因此使用“浮点数abs”。
整数abs”在<cstdlib>中声明。
然而,对于unsigned long long intab都是),不存在重载,因此a-b也是如此;对于long long int的重载仅存在于C++11之后。

C++11在cmath中提供了一个整数重载,点此查看实例,尽管它可能无法满足你的需求...只有gcc实现了它。 - Shafik Yaghmour

1

首先,您需要包含正确的头文件。正如gx_指出的那样,<cmath>具有浮点数绝对值函数,在我的编译器上它实际上可以编译通过,但结果可能与您预期的不同。

1.84467e+19

请使用 <cstdlib> 代替。现在的错误是:
main.cpp:7:30: error: call of overloaded ‘abs(long long unsigned int)’ is ambiguous
main.cpp:7:30: note: candidates are:
/usr/include/stdlib.h:771:12: note: int abs(int)
/usr/include/c++/4.6/cstdlib:139:3: note: long int std::abs(long int)
/usr/include/c++/4.6/cstdlib:173:3: note: long long int __gnu_cxx::abs(long long int)

正如您所看到的,此函数没有 unsigned 重载,因为对于类型为 unsigned 的绝对值进行计算是没有意义的。
我看到有答案建议将 unsigned 类型转换为有符号类型,但我认为这是危险的,除非您确实知道自己在做什么! 首先让我问一下,您要操作的值 ab 的预期范围是什么?如果两者都低于 2^63-1,我强烈建议使用 long long int。然而,如果不是这样,请注意您的程序针对以下值:
a=0, b=1

并且

a=2^64-1, b=0

将会产生完全相同的结果,因为你实际上需要65位来表示任何可能的两个64位值之间的差异。如果您可以确认这不会成为问题,请使用建议的转换。然而,如果您不确定,您可能需要重新考虑您实际想要实现的目标。


-2

因为在 C++ 之前的 C 中,您需要使用 abs、fabs、labs 来处理不同类型的数据,而 C++ 允许对 abs 进行重载。在这种情况下,它可能无法理解或不满意您的重载。

使用 labs(a-b),因为您正在使用 long 类型,这应该可以解决您的问题。


@mahmood 是的,如果a < b,a-b将会溢出(下溢)。abs()无法帮助您检查无符号长长类型的情况。在这种情况下,a-b的结果是一个无符号类型。无符号类型不能为负数。 - nos
是的,就像 @nos 所说的,抱歉我以为这是常识? - gavlaaaaaaaa
long 不等同于 long long - interjay

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