c++ - funcion - ¿Cuál es la diferencia entre abs y fabs?
función abs c++ (3)
Con C ++ 11, usar abs()
solo es muy peligroso:
#include <iostream>
#include <cmath>
int main() {
std::cout << abs(-2.5) << std::endl;
return 0;
}
Este programa produce 2
como resultado. ( Verlo en vivo )
Siempre use std::abs()
:
#include <iostream>
#include <cmath>
int main() {
std::cout << std::abs(-2.5) << std::endl;
return 0;
}
Este programa produce 2.5
.
Puede evitar el resultado inesperado con el using namespace std;
pero me gustaría desaconsejarlo, porque se considera una mala práctica en general y porque hay que buscar la directiva using
para saber si abs()
significa la sobrecarga int
o la sobrecarga double
.
He comprobado la diferencia entre abs
y fabs
en python here
Según tengo entendido, hay algunas diferencias con respecto a la velocidad y los tipos pasados, pero mi pregunta relacionada con c ++ nativo en VS
Con respecto a los VS, probé lo siguiente en Visual Studio 2013 (v120)
:
float f1= abs(-9.2); // f = 9.2
float f2= fabs(-9); // Compile error [*]
Así que fabs(-9)
me dará un error de compilación, pero cuando intenté hacer lo siguiente:
double i = -9;
float f2= fabs(i); // This will work fine
Lo que entiendo del primer código es que no se compilará porque fabs(-9)
necesita un doble, y el compilador no pudo convertir -9 a -9.0, pero en el segundo código el compilador convertirá i=-9
a i=-9.0
en tiempo de compilación, por lo que fabs(i)
funcionará bien.
¿Alguna explicación mejor?
Otra cosa, ¿por qué el compilador no puede aceptar fabs(-9)
y convertir el valor int al doble automáticamente como lo que tenemos en c #?
[*]:
Error: more than one instance of overloaded function "fabs" matches the argument list:
function "fabs(double _X)"
function "fabs(float _X)"
function "fabs(long double _X)"
argument types are: (int)
En C ++, std::abs
está sobrecargado para los tipos de punto flotante y enteros con signo. std::fabs
solo trata con tipos de punto flotante (antes de C ++ 11). Tenga en cuenta que std::
es importante, la función C ::abs
que está comúnmente disponible por razones heredadas solo manejará int
.
El problema con
float f2= fabs(-9);
no es que no haya conversión de int
(el tipo de -9
) a double
, sino que el compilador no sabe qué conversión elegir ( int
-> float
, double
, long double
) ya que hay una std::fabs
para cada uno de esos tres. Su solución le dice explícitamente al compilador que use la conversión int
-> double
, por lo que la ambigüedad desaparece.
C ++ 11 resuelve esto agregando double fabs( Integral arg );
que devolverá el abs
de cualquier tipo de entero convertido al double
. Aparentemente, esta sobrecarga también está disponible en modo C ++ 98 con libstdc ++ y libc ++.
En general, solo use std::abs
, hará lo correcto. ( Interfaz interesante señalada por @Shafik Yaghmour . Los tipos de enteros sin signo hacen cosas graciosas en C ++).
My Visual C ++ 2008 no sabía cuál elegir entre long double fabs(long double)
, float fabs(float)
o double fabs(double)
.
En la declaración double i = -9;
, el compilador sabrá que -9
debe convertirse al double
porque el tipo de i
es double
.
abs()
se declara en stdlib.h
y tratará con el valor int
.
fabs()
se declara en math.h
y tratará con el valor double
.