문제

에 따르면 이 지역 오류 함수 erf (x)는 Math.h에서 제공됩니다. 그러나 실제로 Math.h를보고 있지 않으며 GCC는 다음 테스트 프로그램을 컴파일 할 수 없지만 G ++는 다음과 같습니다.

#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

G ++는 그 GCC를 끌어 당기는 것은 무엇입니까? /usr /include를 살펴보면 erf (x)를 찾을 수있는 유일한 장소는 tgmath.h에 있었으며 포함하지 않습니다. 따라서 G ++는 GCC와 다른 헤더를 잡아야하지만 어느 것이 있습니까?

편집 : LIBM에서 GCC와 링크하지 않았으므로 링크 오류입니다. 그러나 나는 여전히 ERF ()가 수학에없는 이유를 이해하지 못한다. 이것은 어디서 오는 거니?

도움이 되었습니까?

해결책

'erf'는 실제로 Bits/Mathcalls.h로 선언되며, #은 Math.h에 의해 포함됩니다. 실제 선언은 매크로 매직에 의해 크게 가려져 C와 C ++ 모두에게 올바른 일을하게합니다.

다른 팁

나는 비슷한 문제가 있었고 정확한 정의를 찾아야했습니다. erf 그래서 이것에 대해 확장하겠습니다. Chris Dodd가 말했듯이 기능은 bits/mathcalls.h 여기에는 포함됩니다 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
...

매크로 마법이 확장됩니다 __MATHCALL (erf,, (_Mdouble_)); 에게

extern double erf (double) throw (); extern double __erf (double) throw ();

실제 코드가 있습니다 libm.a 또는 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
...

소스는에서 얻을 수 있습니다 GNU LIBC 웹 페이지. 실제 구현에 대한 대략적인 아이디어는 여기서 소스의 몇 줄을 사용합니다.

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     
 ...

수학 라이브러리를 연결해야합니다 (libm) 도:

$ gcc mathHTest.c -lm

모든 정상적인 수학 라이브러리 기능은 실제로 표준 C 라이브러리가 아닙니다 (libc).

내 테스트에 따르면 g++ 포함됩니다 libm 자동으로 gcc 그렇지 않습니다.

x86 프로세서에서 Cygwin의 GCC를 사용하는 것도 같은 문제가있었습니다. "-lm"라이브러리에는 매개 변수가 포함되어 있습니다 (파일 목록 후!)은 완벽하게 작동했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top