Question
Selon ce site , la fonction d'erreur erf (x) vient de math.h. Mais en regardant dans math.h, ce n’est pas là, et gcc ne peut pas compiler le programme de test suivant, tandis que g ++ peut:
#include <math.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
double x;
double erfX;
x = 1.0;
erfX = erf(x);
printf("erf(%f) = %f", x, erfX);
}
$ gcc mathHTest.c
/tmp/ccWfNox5.o: In function `main':
mathHTest.c:(.text+0x28): undefined reference to `erf'
collect2: ld returned 1 exit status
$ g++ mathHTest.c
Qu'est-ce que g ++ n'entraîne pas dans gcc? En regardant dans / usr / include, le seul endroit où j'ai pu trouver erf (x) était dans tgmath.h, ce que je n'inclus pas. Donc, g ++ doit capturer des en-têtes différents de ceux de gcc, mais lesquels?
EDIT: Je ne liais pas dans libm avec gcc, d’où l’erreur de lien. Cependant, je ne comprends toujours pas pourquoi erf () n'est pas dans math.h. D'où vient-il?
La solution
'erf' est en fait déclaré dans bits / mathcalls.h, qui est #included par math.h. La magie des macros occulte lourdement la déclaration proprement dite, ce qui lui permet de faire ce qu'il faut pour le C et le C ++.
Autres conseils
J'ai eu un problème similaire et je devais trouver la définition exacte de erf
, alors laissez-moi développer. Comme l'a dit Chris Dodd, la fonction est déclarée dans bits / mathcalls.h
, qui est incluse dans maths.h
.
bits / mathcalls.h
:
...
#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99
__BEGIN_NAMESPACE_C99
/* Error and gamma functions. */
__MATHCALL (erf,, (_Mdouble_));
__MATHCALL (erfc,, (_Mdouble_));
__MATHCALL (lgamma,, (_Mdouble_));
__END_NAMESPACE_C99
#endif
...
La magie des macros développe __ MATHCALL (erf ,, (_Mdouble _));
à
extern double erf (double) throw (); extern double __erf (double) throw ();
Le code actuel est dans libm.a
ou libm.so
( gcc -lm
):
$ nm /usr/lib/libm.a
...
s_erf.o:
00000400 T __erf
00000000 T __erfc
U __ieee754_exp
00000400 W erf
00000000 W erfc
...
Le source peut être obtenu à partir du gnu libc . page Web. Pour une idée approximative de la mise en oeuvre, voici quelques lignes de la source:
sysdeps / ieee754 / dbl-64 / s_erf.c
:
/* double erf(double x)
* double erfc(double x)
* x
* 2 |\
* erf(x) = --------- | exp(-t*t)dt
* sqrt(pi) \|
* 0
*
* erfc(x) = 1-erf(x)
* Note that
* erf(-x) = -erf(x)
* erfc(-x) = 2 - erfc(x)
*
* Method:
* 1. For |x| in [0, 0.84375]
* erf(x) = x + x*R(x^2)
* erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
* = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
* where R = P/Q where P is an odd poly of degree 8 and
* Q is an odd poly of degree 10.
* -57.90
* | R - (erf(x)-x)/x | <= 2
*
*
* Remark. The formula is derived by noting
* erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
* and that
* 2/sqrt(pi) = 1.128379167095512573896158903121545171688
* is close to one. The interval is chosen because the fix
* point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
* near 0.6174), and by some experiment, 0.84375 is chosen to
* guarantee the error is less than one ulp for erf.
*
* 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
...
Vous devez également lier la bibliothèque mathématique ( libm
):
$ gcc mathHTest.c -lm
Toutes les fonctions normales de la bibliothèque mathématique sont réellement présentes, et pas dans la bibliothèque standard C ( libc
).
Selon mes tests, g ++
inclut libm
automatiquement, mais gcc
ne le fait pas.
J'ai eu le même problème lors de l’utilisation de gcc de cygwin sur un processeur x86. Le " -lm " Le paramètre include de la bibliothèque (après la liste de fichiers!) a parfaitement fonctionné.