الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

برمجة الدوال الرياضية

بدأه C++er في 28 سبتمبر 2008 · 5 رد · 4,685 مشاهدة · في مشاريع ومسابقات القسم
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

كنت قد وضعت سابقا موضوع اسأل فيه عن كيفية عمل دالة 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

1

مدونتي: C++ Tips and Tricks

#2

تلف تلف وترجع للأسمبلي :D

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#3

:lol: :lol: :lol:

صح فى الأخر ملقتش حل غير كده

اه للعلم مايكروسوفت اساسا تضمين الكود الخاص بها لدالة اللوغاريتم و الدوال المثلثيه مبنى على دوال البروسسور

ابقى اعمل disassemble للملف ntdll.dll

و مكتبة runtime للـ c و c++ و .net بيعملوا import للدوال الرياضيه من الملف ntdll.dll

تم تعديل هذه المشاركة بواسطة Game Expert في 28 سبتمبر 2008 في 17:48

مدونتي: C++ Tips and Tricks

#4

طبعاً ... وإلا لماذا تم صنع الـFPU , بالتأكيد لاستخدامه وليس لاعادة برمجة ما يفعله !

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#5

هذه بعض البرامج كنت برمجتها من قبل لعلها تساعدك

اتمنى ان اشترك معك فى هذا المشروع

برنامج حساب التباديل permutations

  1.  
  2. /**
  3. Program : Permuatation
  4. Purpose : calculating permuatation
  5. Programmer : Omar ELadel Mahmoud
  6. Date : 1 Sep 2008
  7. **/
  8. #include <iostream>
  9. using namespace std;
  10.  
  11. long double permutation(long double, long double);
  12. void printnPr() ;
  13. long double factorial(long double);
  14.  
  15. int main(void)
  16. {
  17. printnPr();
  18. long double n , r;
  19. cout << endl << "------------------------" << endl;
  20. do
  21. {
  22. cout << "Enter 0 in N & R to quit !!! " << endl;
  23. cout << "Enter n: " ;
  24. cin >> n;
  25. cout << "Enter r: " ;
  26. cin >> r;
  27. if ( n < 0 || r < 0)
  28. {
  29. cout << "Error .... no negative numbers" << endl;
  30. continue;
  31. }
  32. if ( n < r )
  33. {
  34. cout << "N cannot be smaller than R" << endl;
  35. continue;
  36. }
  37.  
  38. if ( n == 0 && r == 0)
  39. {
  40. break;
  41. }
  42. if ( n != 0 && r == 0)
  43. {
  44. cout << n << "P" << r << " = " << "1" << endl;
  45. continue;
  46. }
  47.  
  48. long double sol = permutation(n,r);
  49. cout << n << "P" << r << " = " << sol << endl;
  50. cout << "------------------------" << endl;
  51. }
  52. while (!(n < 0 || r < 0) );
  53. system("pause");
  54. return 0;
  55. }
  56.  
  57. long double permutation(long double n, long double r)
  58. {
  59. long double perm=1;
  60. perm = factorial(n)/factorial(n-r);
  61. return perm;
  62. }
  63.  
  64. void printnPr()
  65. {
  66. cout << " N" << endl;
  67. cout << " PPPPPPP" << endl;
  68. cout << " PP P" << endl;
  69. cout << " PP P" << endl;
  70. cout << " PPPPPPP" << endl;
  71. cout << " PP " << endl;
  72. cout << " PP " << endl;
  73. cout << " PP " << endl;
  74. cout << " PP R " << endl;
  75. }
  76.  
  77. long double factorial(long double num)
  78. {
  79. double total = 1;
  80. for (int counter = 1 ; counter <= num ; counter++)
  81. {
  82. total *= counter ;
  83.  
  84. }
  85. return total;
  86. }
  87.  

دالة حساب الاس power

  1.  
  2. /*Programmer: Omar Eladel Mahmoud
  3. E-mail: commando_spy161@hotmail.com
  4. Purpose of code: providing function to calculate base rasied
  5. to power instead of pow() in cmath.h
  6. Date: 13-8-2008
  7. */
  8. #include<iostream>
  9. using namespace std;
  10.  
  11. int exponent(long double base, int power)
  12. {
  13. int base2 = base;
  14.  
  15. for (int counter=1; counter < power; counter++)
  16. {
  17. base *= base2;
  18. }
  19. return base;
  20. }
  21.  

برنامج حساب الجذر (الاس الكسرى Fractional Exponenet x ^ (1/n) )

  1.  
  2. #include<iostream>
  3. using namespace std; //function prototype
  4. long double root(float ,float); //function prototype
  5. long double exponent(long double, int); //function prototype
  6.  
  7. //main function
  8. int main()
  9. {
  10. double base;
  11. int exp;
  12. while (base != 0 && exp != 0 )
  13. {
  14. cout << "Enter base: ";
  15. cin >> base;
  16. cin.ignore();
  17. cout << "Enter fractional exponent (1/x): 1/ ";
  18. cin >> exp;
  19. cin.ignore();
  20.  
  21. if ((base < 0) && (exp % 2 == 0 ))
  22. {
  23. cout << "Error evaluating root" << endl;
  24. system("pause");
  25. return 0;
  26. }
  27. if (exp == 0)
  28. {
  29. cout << "Error evaluating root" << endl;
  30. system("pause");
  31. return 0;
  32. }
  33. long double sol = root(base,exp); //applying root function
  34. cout << exp << "nth root of " << base << " is: " << sol << endl;
  35. }
  36. system("pause");
  37. return 0;
  38. }
  39.  
  40. //exponent function needed for calculating root
  41. long double exponent(long double base, int power)
  42. {
  43. long double base2 = base;
  44.  
  45. for (int counter=1; counter < power; counter++)
  46. {
  47. base *= base2;
  48. }
  49. return base;
  50. }
  51.  
  52. //root function
  53. long double root(float base, float exp)
  54. {
  55. long double x = 1;
  56. for (int i=1; i<= 900000; i++) //loop for iteration
  57. {
  58. x = (1/exp)*(((exp-1)*x)+(base /exponent(x,exp-1))); //applying (Iterative calculation of an nth root)
  59. }
  60. return x;
  61. }
  62.  

دالة حساب المضروب factorial

  1.  
  2. #include<iostream>
  3. using namespace std;
  4.  
  5. int factorial(long double num)
  6. {
  7. double total = 1;
  8. for (int counter = 1 ; counter <= num ; counter++)
  9. {
  10. total *= counter ;
  11.  
  12. }
  13. cout << "Factorial: " << total << endl;
  14. }
  15.  

بعض الافطار بأذن الله سأرفع الملفات و البرامج التنفيذية

وفقكم الله

#6

محتويات الملف :

1- برنامج حل معادلات الدرجة الاولى و الثانية

2- برنامج حساب مضروب العدد Factorial

3- برنامج حساب الاس Exponent

4- برنامج حساب الجذور Fractional Exponent

5- برنامج حساب التباديل Permutations

Math.rar

مواضيع مشابهة