![](/img/trans.png)
[英](Rcpp)armadillos abs() function outputs false values when used with c++ double while std::abs works
[英]On the std::abs function
是否为C ++ 11中的所有算术类型定义了std::abs()
函数,并返回|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]:
除了
<cstdlib>
中某些数学函数的int
版本之外,C ++还添加了这些函数的long
和long long
重载版本,具有相同的语义。添加的签名是:
long abs(long); // labs() long long abs(long long); // llabs()
[...]
除了
<cmath>
中的数学函数的double
版本,这些函数的重载版本具有相同的语义。 C ++添加了这些函数的float
和long double
重载版本,具有相同的语义。float abs(float); long double abs(long double);
所以你应该确保正确包含<cstdlib>
( int
, long
, long long
overloads)/ <cmath>
( double
, float
, long double
overload)。
您不能保证std::abs(x)
将始终返回|x|
适用于所有算术类型。 例如,大多数有符号整数实现的空间比正数多一个,所以abs(numeric_limits<int>::min())
不等于|x|
。
请检查您实际上是使用std::abs
从<cstdlib>
而不是std::abs
从<cmath>
PS。 哦,刚看到示例程序,好吧,你去了,你正在使用std::abs
的浮点重载之一。
当您使用带有整数类型的<cmath>
std::abs
时,g ++(使用C ++ 11标准)返回double并不奇怪:来自http://www.cplusplus.com/reference/cmath/abs/ :
从C ++ 11开始,此标题(
<cmath>
)中为整数类型提供了额外的重载:这些重载在计算之前有效地将x转换为double(定义为T为任何整数类型)。
这实际上是在/usr/include/c++/cmath
:
template<typename _Tp>
inline _GLIBCXX_CONSTEXPR
typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
double>::__type
abs(_Tp __x)
{ return __builtin_fabs(__x); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.