c++ - 在 std::abs 函数上

标签 c++ c++11 standards-compliance absolute-value

std::abs() 函数是否为 C++11 中的所有算术类型定义良好,并且将返回 |x| 而没有近似问题?

奇怪的是,对于 g++4.7,std::abs(char), std::abs(short int), std: :abs(int), std::abs(long int)std::abs(long long int) 似乎返回一个 double (在相反:http://en.cppreference.com/w/cpp/numeric/math/abs)。如果将数字转换为 double ,对于非常大的数字(如 -9223372036854775806LL = 2^63-3),我们可能会有一些近似误差。

那么我是否保证 std::abs(x) 将始终为所有算术类型返回 |x|

编辑:这是一个进行一些测试的示例程序

#include <iostream>
#include <iomanip>
#include <cmath>
#include <typeinfo>

template<typename T>
void abstest(T x)
{
    static const unsigned int width = 16;
    const T val = x;
    if (sizeof(val) == 1) {
        std::cout<<std::setw(width)<<static_cast<int>(val)<<" ";
        std::cout<<std::setw(width)<<static_cast<int>(std::abs(val))<<" ";
    } else {
        std::cout<<std::setw(width)<<val<<" ";
        std::cout<<std::setw(width)<<static_cast<T>(std::abs(val))<<" ";
    }
    std::cout<<std::setw(width)<<sizeof(val)<<" ";
    std::cout<<std::setw(width)<<sizeof(std::abs(val))<<" ";
    std::cout<<std::setw(width)<<typeid(val).name()<<" ";
    std::cout<<std::setw(width)<<typeid(std::abs(val)).name()<<std::endl;
}

int main()
{
    double ref = -100000000000;
    abstest<char>(ref);
    abstest<short int>(ref);
    abstest<int>(ref);
    abstest<long int>(ref);
    abstest<long long int>(ref);
    abstest<signed char>(ref);
    abstest<signed short int>(ref);
    abstest<signed int>(ref);
    abstest<signed long int>(ref);
    abstest<signed long long int>(ref);
    abstest<unsigned char>(ref);
    abstest<unsigned short int>(ref);
    abstest<unsigned int>(ref);
    abstest<unsigned long int>(ref);
    abstest<unsigned long long int>(ref);
    abstest<float>(ref);
    abstest<double>(ref);
    abstest<long double>(ref);
    return 0;
}

最佳答案

保证<cmath> 中存在正确的重载/<cstdlib> :

C++11,[c.math]:

In addition to the int versions of certain math functions in <cstdlib>, C++ adds long and long long overloaded versions of these functions, with the same semantics.

The added signatures are:

long abs(long);            // labs()
long long abs(long long);  // llabs()

[...]

In addition to the double versions of the math functions in <cmath>, overloaded versions of these functions, with the same semantics. C++ adds float and long double overloaded versions of these functions, with the same semantics.

float abs(float);
long double abs(long double);

所以你应该确保正确地包含 <cstdlib> ( int , long , long long 过载)/<cmath> (doublefloatlong double 过载)。

关于c++ - 在 std::abs 函数上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13460750/

相关文章:

c - C 中的非 ASCII 字符

c++ - -ffast-math 可以安全地用于典型项目吗?

c++ - 如何修复 "use of class template requires template argument list"

c++ - 根据模板参数选择合适的复制构造函数

c++ - 由 XML 文件配置的 Linux C++ 应用程序设置

c++ - 为什么像 cin、cout、string 等被认为是对象?

c++ - 为什么编译器不能解析 std::function 参数的重载?

c++ - 如何初始化嵌套结构的 unique_ptr (例如二叉树)

c++ - 由于哪个版本的 GCC 支持 C++14?

c++ - `cname` 和 `name.h` 中的类型可以是不同的类型吗?