在std :: abs函数上

Vin*_*ent 20 c++ standards-compliance absolute-value c++11

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

一个奇怪的是,与G ++ 4.7, ,std::abs(char),,std::abs(short int) 和似乎回到了双(对相反:http://en.cppreference.com/w/cpp/numeric/math/abs).如果数字被转换为double,我们可能会对非常大的数字(例如)有一些近似误差.std::abs(int)std::abs(long int)std::abs(long long int)-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;
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*lia 16

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

C++ 11,[c.math]:

除了int某些数学函数的版本之外<cstdlib>,C++还添加longlong long重载了这些函数的版本,具有相同的语义.

添加的签名是:

long abs(long);            // labs()
long long abs(long long);  // llabs()
Run Code Online (Sandbox Code Playgroud)

[...]

除了double数学函数的<cmath>版本,这些函数的重载版本,具有相同的语义.C++ 使用相同的语义添加floatlong double重载这些函数的版本.

float abs(float);
long double abs(long double);
Run Code Online (Sandbox Code Playgroud)

所以,你应该确保正确包括<cstdlib>(int,long,long long过载)/ <cmath>(double,float,long double过载).

  • 第26.8.7-9节,以防任何人关心. (6认同)

Rob*_*per 5

您不能保证std::abs(x)总是返回|x|所有算术类型。例如,大多数有符号整数实现的空间比正数多一个负数,因此abs(numeric_limits<int>::min())will 的结果不等于|x|