سؤال

ووفقا ل هذا الموقع في ERF دالة الخطأ (خ) ويأتي من math.h. ولكن إذا نظرنا في الواقع في math.h، فإنه ليس هناك، ودول مجلس التعاون الخليجي لا يمكن ترجمة البرنامج الاختبار التالي بينما ز ++ القيام بما يلي:

#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

وماذا ز ++ في ذلك سحب دول مجلس التعاون الخليجي لا؟ أبحث في / البيرة / وتشمل، المكان الوحيد الذي يمكن أن تجد ERF (س) كان في tgmath.h، التي لا تشمل. لذا ز ++ يجب الاستيلاء على رؤوس مختلفة من دول مجلس التعاون الخليجي، ولكن ما هي؟

وتحرير: لم أكن ربط في libm مع دول مجلس التعاون الخليجي، وبالتالي الخطأ الارتباط. ومع ذلك، ما زلت لا أفهم لماذا ERF () ليست في math.h. حيث أنها تأتي من؟

هل كانت مفيدة؟

المحلول

و"ERF" يعلن فعلا في بت / mathcalls.h التي كتبها #included math.h. تحجب الإعلان الفعلي بشكل كبير بفعل السحر الكلي لجعلها تفعل الشيء الصحيح لكلا C و C ++

نصائح أخرى

وكان لي مشكلة مماثلة، وهناك حاجة للعثور على التعريف الدقيق لerf لذلك اسمحوا لي أن أتوسع في هذا الشأن. كما قال كريس دود تم الاعلان عن وظيفة في 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
...

ويمكن الحصول على مصدر من جنو 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. وتشمل "-lm" مكتبة المعلمة (بعد قائمة الملفات!) عملت تماما.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top