c++ - libreria - how to install library e1071
En la funciĆ³n std:: abs (4)
¿Está bien definida la función std::abs()
para TODOS los tipos aritméticos en C ++ 11 y devolverá |x|
¿Sin problema de aproximación?
Una cosa rara es que con g ++ 4.7, std::abs(char)
, std::abs(short int)
, std::abs(int)
, std::abs(long int)
y std::abs(long long int)
parece devolver un doble (a diferencia de: http://en.cppreference.com/w/cpp/numeric/math/abs ). Y si el número se convierte en un doble, podríamos tener algún error de aproximación para un número muy grande (como -9223372036854775806LL = 2^63-3
).
Entonces, ¿tengo la garantía de que std::abs(x)
siempre devolverá |x|
para todos los tipos aritméticos?
EDITAR: aquí hay un programa de ejemplo para hacer algunas pruebas
#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;
}
Compruebe que de hecho está utilizando std::abs
de <cstdlib>
y no std::abs
de <cmath>
.
PD. Oh, acabo de ver el programa de ejemplo, bueno, ya está, está usando una de las sobrecargas de punto flotante de std::abs
.
No es extraño que g ++ (con el estándar C ++ 11) devuelva un doble cuando usas std::abs
de <cmath>
con un tipo integral: From http://www.cplusplus.com/reference/cmath/abs/ :
Desde C ++ 11, se proporcionan sobrecargas adicionales en este encabezado (
<cmath>
) para los tipos integrales: estas sobrecargas<cmath>
efectivamente x en un doble antes de los cálculos (definido para T como cualquier tipo integral).
Esto se implementa de la misma manera en /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); }
No puede garantizar que std::abs(x)
siempre devolverá |x|
Para todos los tipos aritméticos. Por ejemplo, la mayoría de las implementaciones de enteros con signo tienen espacio para un número negativo más que un número positivo, por lo que los resultados de abs(numeric_limits<int>::min())
no serán iguales |x|
.
Se garantiza que las sobrecargas correctas están presentes en <cmath>
/ <cstdlib>
:
C ++ 11, [c.math]:
Además de las versiones
int
de ciertas funciones matemáticas en<cstdlib>
, C ++ agrega versiones sobrecargadaslong
ylong long
de estas funciones, con la misma semántica.Las firmas agregadas son:
long abs(long); // labs() long long abs(long long); // llabs()
[...]
Además de las versiones
double
de las funciones matemáticas en<cmath>
, las versiones sobrecargadas de estas funciones, con la misma semántica. C ++ agrega versionesfloat
ylong double
sobrecargadas de estas funciones, con la misma semántica.
float abs(float); long double abs(long double);
Por lo tanto, debe asegurarse de incluir correctamente <cstdlib>
( int
, sobrecargas long
, long long
) / <cmath>
( double
, float
, sobrecargas long double
).