بتـــــاريخ : 2/22/2011 7:26:39 PM
الفــــــــئة
  • الحـــــــــــاسب
  • التعليقات المشاهدات التقييمات
    0 1134 0


    برمجة الدوال الرياضية لتعمل تماما مثل الموجوده فى المكتبه cmath

    الناقل : elmasry | العمر :42 | الكاتب الأصلى : محمد علاء الدين | المصدر : www.arabteam2000-forum.com

    كلمات مفتاحية  :

    كنت قد وضعت سابقا موضوع اسأل فيه عن كيفية عمل دالة sin و cos و كذلك دالة الأس و الجذر. و تم أرشادى لبعض الحلول لذا فقد بحثت عن افضل الأساليب لتضمينهم فوجدت ان افضلهم بلغة التجميع حيث ان بعض تلك الدوال معرفة للبروسسور. طبعا كتابة الكود لجميع الدوال بلغة التجميع غير فعالة - بالنسبة لى على الأقل. دعونى لا اطيل عليكم و اعطيكم النتيجة بشكل مباشر

    struct Math
    {
            static double log(double x);    // Return natural logarithm of x (also called ln of x)

            static double log10(double x); // Return logarithm to base 10 of x

            static double exp(double x);    // Return exponent of x

            static double alog10(double x); // Return anti-logarithm of x

            static double pow(double base,double exp); // Return base raised to exp

            static double root(double base,double exp); // Return base root of exp

            static double sqrt(double base);                   // Return Square root of base

            static double abs(double x);              // Return absolute value of x

            static long mod(long x,long y); // Return the Reminder of dividing x over y

            static unsigned long long factorial(unsigned long long x);        // Return Factorial of x

            static double floor(double x); // Returns the largest integer less than or equal to x

            static double ceiling(double x); // Returns the smallest integer greater than or equal to x

            static double sin(double x); // Return sine of x

            static double cos(double x); // Return cosine of x

            static double tan(double x); // Return tangent of x

            static double asin(double x); // Return angel (in radians) whose sine is x

            static double acos(double x); // Return angel (in radians) whose cosine is x

            static double atan(double x); // Return angel (in radians) whose tangent is x

            static double sinh(double x); // Return Hyperbolic sine of x

            static double cosh(double x); // Return Hyperbolic cosine of x

            static double tanh(double x); // Return Hyperbolic tangent of x

            static double asinh(double x); // Return angel (in radians) whose hyperbolic sine is x

            static double acosh(double x); // Return angel (in radians) whose hyperbolic cosine is x

            static double atanh(double x); // Return angel (in radians) whose hyperbolic tangent is x

            static long permute(long x, long y); // Return permutation of two numbers x and y
            static long combin (long x, long y); // Return combination of two numbers x and y

            static float* Pol(float x, float y);      // Return 2 Element array contain r and theta(in radian) respectively in polar coordinate
            static float* Rec(float r, float theta); // Return 2 Element array contain x and y respectively in rectangular coordinate
    };


    عدد الدوال السابقه 28 دالة، منهم 11 دالة لم اقم بتضمينهم لضيق الوقت و لكنى سأقوم ان شاء الله إن وجدت متسع من الوقت. الدوال الـ 11 هى
    asin , acos , atan , sinh , cosh , tanh , sinh , acosh , atanh , Pol , Rec

    الكود الخاص بالدوال السابقه هو
    // preprocessor constants
    #define PI         3.14159265358979323846 // pi constant
    #define E               2.71828182845904523536 // exponent constant

    // preprocessor macros
    #define ToDegree(RAD) ((RAD * 180) / PI)
    #define ToRadian(DEG) ((DEG * PI ) / 180)


    // Private Interger power
    double internalPwr(double num,int pwr)
    {
            double sum=1;

            for(int i=1;i<=pwr;i++)
                    sum*=num;

            return sum;
    }

    long factor_condition(long from, long to)
    {
            long sum=1;
            for (long i=from; i>=to; i--)
                    sum*=i;

            return sum;
    }
    double Math::log(double x)
    {
            _asm
            {
                    fld   x   // push the x parameer into stack
                    fld1             // push 1 to stack (because fyl2x require that st(0) to be greater than 0)
                    fxch             // swap st(1) and st(0)
                    fyl2x           // Compute 1 * log(x)
                    fldl2e     // Load e
                    fdiv             // apply the division log(x)/log(e)
            }
    }

    double Math::log10(double x)
    {
            const double base10 = 2.3025850929940456840179914546844;
            return log(x) / base10;
    }

    double Math::exp(double x)
    { return pow(E,x); }

    double Math::alog10(double x)
    {
            const double multi = x * 3.3219280948873626; // x *  ln(10)/ln(2)
            _asm
            {
                    fld      multi   // push multi on top of floating-point stack
                    fld st(0)                // Duplicate tos.
                    fld st(0)
                    frndint            // Compute integer portion.
                    fxch                      // Swap whole and int values.
                    fsub st(0), st(1) // Compute fractional part.
                    f2xm1                    // Compute 2^frac(x)-1.
                    fld1
                    fadd                      // Compute 2^frac(x).
                    fxch                      // Get integer portion.
                    fld1                      // Compute 1*2**int(x).
                    fscale
                    fstp st(1)              // Remove st(1) (which is 1).
                    fmul                      // Compute 2^int(x) * 2**frac(x).
            }
    }

    double Math::pow(double base,double exp)
    { return alog10(log10(base) * exp); }

    double Math::root(double base,double exp)
    { return alog10(log10(base) / exp); }

    double Math::sqrt(double base)
    {return root(base,2); }

    double Math::abs(double x)
    { return x<0 ? -x : x; }

    long Math::mod(long x,long y)
    { return x - ((x/y) * y); }

    unsigned long long Math::factorial(unsigned long long x)
    {
            unsigned long long sum=1;
            for (unsigned long long i=x; i>=1; i--)
                    sum*=i;

            return sum;
    }

    double Math::ceiling(double x)
    { return (double)((x > (long)x) ? ((long)x+1) : ((long)x) ); }

    double Math::floor(double x)
    { return (double)((x < (long)x) ? ((long)x-1) : ((long)x) ); }

    double Math::sin(double x)
    {
            float angel[]={0,30,90,180,210,270,360}; // angle lookup table for readable number and
            float values[]={0,0.5,1,0,-0.5,-1,0}; // it's values in degree

            double deg=ToDegree(x); // convert x to degree

            for (;;)
                    if (deg>=360)     // if x greater than 360
                            deg-=360; // decrease it by 360
                    else                       // otherwise
                            break; // break infinite loop

            for (int c=0; c<7; c++)           // search look up table for angle
                    if (deg==angel[c])              // if exist
                            return values[c]; // return its value

            // now i'll calculate sin using formula
            // sin x = x - (x^3/3!) + (x^5/5!) - (x^7/7!) ....

            double numerator = x;
            double denominator = 1.0;
            double sign = 1.0;
            double value = 0;

            for ( int i = 1; i <= 10; i++ )
            {
                    value += numerator / denominator * sign;
                    numerator *= x * x;
                    denominator *= i*2 * (i*2+1);
                    sign *= -1;
            }
           
            return value;
    }

    double Math::cos(double x)
    {
            float angel[]={0,90,120,180,270,300,360};
            float values[]={1,0,-0.5,-1,0,0.5,1};

            double deg=ToDegree(x);

            for (;;)
                    if (deg>=360)
                            deg-=360;
                    else
                            break;

            for (int c=0; c<7; c++)
                    if (deg==angel[c])
                            return values[c];

            double numerator = 1.0;
            double denominator = 1.0;
            double sign = 1.0;
            double cos = 0;

            for ( int i = 1; i <= 10; i++ )
            {
                    cos += numerator / denominator * sign;
                    sign *= -1;
                    numerator *= x * x;
                    denominator *= (i*2-1) * i*2;
            }
           
            return cos;
    }

    double Math::tan(double x)
    { return sin(x)/cos(x); }

    long Math::permute(long x, long y)
    {
            // معادلة حساب التباديل لرقمين x و y
            if (y>x)
                    throw "y can not be greater than x";

            if (y==1)
                    return x;

            if (y==0)
                    return 1;

            if (x==y || x==y-1)
                    return factor_condition(x,2);

            return factor_condition(x,x-y+1);
    }

    long Math::combin(long x, long y)
    {
            // معادلة حساب التوافيق لرقمين x و y
            if (y>x)
                    throw "y can not be greater than x";

            if (y==1 || x==y-1)
                    return x;

            if (y==x || y==0)
                    return 1;

            return factor_condition(x,x-y+1)/factor_condition(y,2);
    }


    بالنسبة للداله internalPwr تقوم بحساب الأس لرقم صحيح موجب
    بالنسبه للداله factor_condition تقوم بحساب مضروب ما بين رقمين بمعنى لحساب مضروب ما بين الرقم 9 و 5 يكون 9 * 8 * 7 * 6 * 5 و هذه الدالة تستخدم فقط مع الدالتين permute و combin.

    فى المرفثقات ستجد مشروع تطبيقى بسيط ليوضح الفرق بينها و بين مكتبة cmath

    و الله ولى التوفيق
    ملف مرفق  TestMath.rar (3.96كيلو )

    كلمات مفتاحية  :

    تعليقات الزوار ()