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 .