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

مساعده في سلسله تايلور

رائج
بدأه empror9 في 9 يوليو 2010 · 59 رد · 3,225 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

جمعتكم مباركه ان شاء الله *_^

الرجاء مشاهدة الصوره التاليه 457215330.jpg

مطلوب مني ان اقوم بسؤال المستخدم لادخال قيمه الاكس ، ثم بعد ذلك اقوم بطباعه cos, sin ,tan الاكس

المشكله لما اطبق القانون على الاله الحاسبه تطلع بنتيجه مختلفه عن الامثله الموجوده في السؤال

هنا مثال

قيمه اكس هي = 2.3145000 (( على حسب المثال الموجود في السؤال عندي))

النتايج هي كالتالي

sin = 0.7359662

cos = -0.6770183

tan = -1.0870698

وبالنسبه لي عند حساب الاكس وبتعويضهم في القوانين ماتظهر لي نفس النتيجه يعني في البدايه ياريت مساعده في فهم القانون حتى اقوم بترجمتها بشكل صحيح في لغه c++

الرجاء ملاحظه اني ضعيف في الرياضيات + مبتدا نوعا ما في لغه c++ ((اعرف فقط if,swhich,while , for , function))

أنتظركم

#2

الان صحيح اذا كتبت sin(2.3.145) سيعطيني الناتج 0.735966

لكن مافائده القوانين؟

#3

السلام عليكم و رحمة الله و بركاته

اقتباس
المشكله لما اطبق القانون على الاله الحاسبه تطلع بنتيجه مختلفه عن الامثله الموجوده في السؤال

لا يوجد أي اختلاف يا أخي العزيز , كل ما في الأمر أنه يوجد 3 وحدات لقياس الزوايا وهي:

الراديان (Radians) و الدرجة (Degrés) و لكراد (Grades) , فقط.

الزاوية المُعطاة في التمرين هي بقياس الراديان و لكي تجد نفس النتيجة (عن طريق الحاسبة) قم بتحويل القياس إلى الدرجة حيث توجد 3 خيارات هي الراديان و الدرجة و لكراد.

أما إذا كنت تريد تحويل زاوية من الراديان إلى الدرجة فيمكنمك فعل ذلك بالقانون التالي:

180 تقابلها pi

y تقابلها 2.3145000

حسب القاعدة الثلاثية فإن:

y*pi=2.3145000*180

مما يعني أن :

y=(2.3145000*180)/pi

y=416.61/3.141592

إذن:

y=132.611081

و هي الزاوية التي تقابل x بقياس الدرجة.

لاحظ أن:

 sin(x)

بقياس الرا ديان يساوي:

 sin(y)

بقياس الدرجة لأن الزوايا متساوية و الذي يختلف هو نوع القايس.

ملاحظة (للفائدة العامة):

ستحتاج إلى طريقة التحويل (من قياس الراديان إلى قياس الدرجة) عندما تستعمل إحدى الدوال tan,cos,sin (الموجودة في المكتبة cmath) لأن النتيجة التي ستحصل عليها ستكون بقياس الراديان.

طبعا في هذا التمرين لن تستخدم الدوال tan,cos,sin وإنما تحتاج إلى معرفة طريقة كتابة الدوال التراجعية.

اقتباس
لأن النتيجة التي ستحصل عليها ستكون بقياس الراديان.

النتيجة التي ستحصل عليها عبارة عن قيمة لجيب الزاوية (مثلا) و لا يوجد قياس للقيم و إنما يكون القياس للوحدات حيث توجد ثلاث قياسات للزوايا (كما ذكرتُ آنفا).

الملاحظة باختصار هي أنك في بعض الأحيان تحتاج إلى تحويل زاوية من قياس إلى قياس آخر .. عندها ستستعمل الطريقة الموضحة أعلاه :)

في امان الله.

تم تعديل هذه المشاركة بواسطة أحمد المتألق في 9 يوليو 2010 في 17:44

2
#5

السلام عليكم

إلى الأستاذ محمد علاء:

الأخ empror9 قال بأنه:

اقتباس
الرجاء ملاحظه اني ضعيف في الرياضيات + مبتدا نوعا ما في لغه c++ .. اعرف فقط:

if,swhich,while , for , function

و أنت قلت:

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

فلكي يفهم الموضوع لا بد و أن يكون له إلمام بلغة التجميع و هذا أمر لم يتحقق بعد :blush: لذلك فإنني أرجوا منك أن تعطينا طريقة بسيطة .. تعتمد على الفصول الأولى (كالتي ذكرها الأخ empror9 ) حتى نفهم جميعا :)

بالمناسبة فقد حاولت التمرين باستخدام الدوال التراجعية و أرجو منكم التصحيح إذا كان هناك خطأ:

float sin(int x,int r)
{
  int i=0,n=0;
  n+=2*n+1;
  while(n!=r)
  {
    if(x==0) return 1;
	else
	{
	   if(++i%2!=0)
        return (x*sin(x,n-1)/n*sin(n-1));
       else
        return (-x*sin(x,n-1)/n*sin(n-1));
    }
  }
}

تحياتي :)

1
#6
أحمد المتألق كتب:

السلام عليكم و رحمة الله و بركاته

لا يوجد أي اختلاف يا أخي العزيز , كل ما في الأمر أنه يوجد 3 وحدات لقياس الزوايا وهي:

الراديان (Radians) و الدرجة (Degrés) و لكراد (Grades) , فقط.

الزاوية المُعطاة في التمرين هي بقياس الراديان و لكي تجد نفس النتيجة (عن طريق الحاسبة) قم بتحويل القياس إلى الدرجة حيث توجد 3 خيارات هي الراديان و الدرجة و لكراد.

أما إذا كنت تريد تحويل زاوية من الراديان إلى الدرجة فيمكنمك فعل ذلك بالقانون التالي:

180 تقابلها pi

y تقابلها 2.3145000

حسب القاعدة الثلاثية فإن:

y*pi=2.3145000*180

مما يعني أن :

y=(2.3145000*180)/pi

y=416.61/3.141592

إذن:

y=132.611081

و هي الزاوية التي تقابل x بقياس الدرجة.

لاحظ أن:

 sin(x)

بقياس الرا ديان يساوي:

 sin(y)

بقياس الدرجة لأن الزوايا متساوية و الذي يختلف هو نوع القايس.

ملاحظة (للفائدة العامة):

ستحتاج إلى طريقة التحويل (من قياس الراديان إلى قياس الدرجة) عندما تستعمل إحدى الدوال tan,cos,sin (الموجودة في المكتبة cmath) لأن النتيجة التي ستحصل عليها ستكون بقياس الراديان.

طبعا في هذا التمرين لن تستخدم الدوال tan,cos,sin وإنما تحتاج إلى معرفة طريقة كتابة الدوال التراجعية.

النتيجة التي ستحصل عليها عبارة عن قيمة لجيب الزاوية (مثلا) و لا يوجد قياس للقيم و إنما يكون القياس للوحدات حيث توجد ثلاث قياسات للزوايا (كما ذكرتُ آنفا).

الملاحظة باختصار هي أنك في بعض الأحيان تحتاج إلى تحويل زاوية من قياس إلى قياس آخر .. عندها ستستعمل الطريقة الموضحة أعلاه :)

في امان الله.

اهلا استاذي احمد

الان وضحت الصوره لي اكثر ، يعني افهم من كلامك ان اذا كانت القيمه بالراديان احولها للدرجه حتى استطيع ان استخدم القوانين صح؟

طيب انا سويت كذا ونفس الحكايه النتيجه غير صحيحه

شوف تطبيقي هنا

القيمه 2.3145000 مضروبه في 180 ثم نقسمهم على 3.141592 ليصبح الناتج 132.6111 والي هي القيمه بالدرجه

لاان اعوض بالقانون للساين مثلا = 132.6111 - 132.6111^3/3*2*1 وهكذا لين ينتهي القانون وتطلع لي نتيجه مختلفه

ياريت تصحيح لكلامي اذا فيه خطا

تحياتي،،

#7

الاستاذ محمد علاء الدين شاكر لك ردك الكريم وصحيح ماذكره الاخ خالد بخصوص اني مبتدا ههههه ولا فهمت شئ

اخ خالد مشكور جدا لمرورك الكريم وتعليقك

#8

السلام عليكم أخي الكريم

بما أنك مبتدئ كتبت لك هذا الكود - ويعطي نتائج معقولة جدا

طبعاً هو تطبيق مباشر على المتتالية التي كتبتها

ملحوظات :

1- القانون يسري على الراديان فقط

2- السبب أنه لا يعطي نتائج صحيحة 100% هو أن قيمة الاقترانات المثلثية هي ناتج تطبيق المتتالية حتى المالانهاية ، وهذا ما يصعب تطبيقه في البرمجة لأن هناك حداً لكل نوع بيانات data type لا يمكن أن يتعداه .

#include<iostream>
using namespace std;

const float pi = 3.1415926;

int fact(int x)
{
	int result = 1;

	for(int i=2 ; i<=x ; i++)
		result *= i;

	return result;
}

double pow(double x,double y)
{
	double result=x;

	for(int i=1 ; i<y ; i++)
		result *= result;

	return result;
}

float sin(float x)
{
	float result = x;

	int limit = 10;
	int sign = -1;

	for(int i=3 ; i<limit ; i+=2,sign=-sign)
		result += sign*pow(x,i)/fact(i);

	return result;
}

float cos(float x)
{
	float result = 1;

	int limit = 10;
	int sign = -1;

	for(int i=2 ; i<limit ; i+=2,sign=-sign)
		result += sign*(pow(x,i)/fact(i));

	return result;
}

float tan(float x)
{
	return sin(x)/cos(x);
}

int main()
{
	cout<<tan(pi/4)<<endl;

	return 0;
}
3

البرمجة = الرياضيات

#9

السلام عليكم و رحمة الله و بركاته

اقتباس
اهلا استاذي احمد

:blush: :blush: :blush:

اقتباس
افهم من كلامك ان اذا كانت القيمه بالراديان احولها للدرجه حتى استطيع ان استخدم القوانين صح؟

لا :wink: القانوان يُطبق مع الزوايا ذات قياس الراديان :) و الهدف من الطريقة الموضحة أعلاه هو معرفة التحويل من قياس معين إلى قياس آخر.

سأثبت لك أن القانون يُطبق مع الزوايا ذات قياس الراديان :wink: و سنستخدم الطريقة التي ذكرتُها بالأعلى.

أولا سنأخذ قيمة للزاوية x و يُستحسن أن تكون صغيرة حتى لا تطول الحسابات .. لنأخذ مثلا x=1 بقياس الراديان, بتطبيق القاعدة المذكورة نجد أن x=57.295779 بقياس الدرجة, الحين ندخل في الحسابات:

بداية .. نعلم أن:

3!=6
5!=120
7!=5040
9!=362880

الآن نقوم بالتعويض:

sin(1)=1-1/6+1/120-1/5040+1/362880
sin(1)=1-0.166666+0.008333-0.000198+0.000000
sin(1)=841484

طيب الآن سنحسب:

sin(1)

عن طريق الحاسبة و نضبط الإعدادت على قياس الراديان , فنجد:

sin(1)=84147098480789650

و هي النتيجة التي حصلنا عليها سابقا :)

بالنسبة للنتجية التي حصلنا عليها من قانون تايلور:

إذا كنا نريد الحصول على نتيجة أكثر دقة فيمكننا تمديد نشر تايلور إلى أن نصل إلى الأس 17 مثلا.

ملاحظة:قد لا أجد الوقت الكافي لمتابعة الموضوع و لكن الإخوة لن يقصروا معك :)

في أمان الله.

تم تعديل هذه المشاركة بواسطة أحمد المتألق في 9 يوليو 2010 في 18:44

1
#11

اشكرك جزيل الشكر اخوي namespace على الكود والاضافه الجميله

مشكور جدا استاذ احمد كثير وضحت الصوره بس ليه لما استخدم الطريقه هذي مايطلع صح sin(1) = 1 - 1^3/3*2*1 + 1^5/5*4*3*2*1 and so on

؟؟ هنا الي رافع ضغطي فعلا

#12

السلام عليكم

اقتباس
ليه لما استخدم الطريقه هذي مايطلع صح

sin(1) = 1 - 1^3/3*2*1 + 1^5/5*4*3*2*1 and so on

انتبه جيدا أخي empror9 :excl:

الأخ أحمد قام بنفس الطريقة ثم قام بالتعويض:

1^3=1^5=1^7=1^9=1
3!=3*2*1=6
5!=5*4*3*2*1=120
7!=7*6*5*4*3*2*1=5040
9!=9*8*7*6*5*4*3*2*1=362880

تحياتي :)

#13
اقتباس
ألا يمكننا جمع الدوال fact و pow في دالة واحدة كما فعلتُ أنا ؟

يمكن - لكن ليس كما فعلت أنت :lol:

اقتباس
بالمناسبة فقد حاولت التمرين باستخدام الدوال التراجعية و أرجو منكم التصحيح إذا كان هناك خطأ

تقصد أن تسأل أين الخطأ

float sin(int x,int r)
{
  int i=0,n=0;
  n+=2*n+1;
  while(n!=r)
  {
    if(x==0) return 1;
        else
        {
           if(++i%2!=0)
        return (x*sin(x,n-1)/n*sin(n-1));
       else
        return (-x*sin(x,n-1)/n*sin(n-1));
    }
  }
}

- في البداية اقتران ال sin يستقبل قيم من نوع int وهذا خطأ أول

- ثم السطر التالي خارج الدوران مع أن الأصل أن يكون داخله ، لأن شرط الدوران يعتمد على n

n+=2*n+1;

- أيضاً قمت بعمل استدعاء ذاتي وفي نفس الوقت لدينا دوران while ! وهنا ندخل في متاهة لا مخرج منها ، واحتمال الدوران اللانهائي كبير جداً كما في حلك

أليس الاستدعاء الذاتي ليغنينا عن الدوران ، أليس الاستدعاء الذاتي يفعل ما يعجز عنه الدوران ، وإلا فإن كان الأمر متاحاً بدوران بسيط فلم الاستدعاء الذاتي ؟

لا مفر منه إذا أردت أن تكتب برنامجاً ليقوم بحل متاهة ، أو في هيكلة البيانات وبالتحديد trees ، أو . . .

.نرجع إلى سؤالك

اقتباس
ألا يمكننا جمع الدوال fact و pow في دالة واحدة

يمكننا لكن لن نستفيد من ذلك ، سنضع حينها الكودين بجانب بعضهما في اقتران واحد ، ونجعل result1 كنتيجة للأول و result2 كنتيجة للثاني ونرجع result1/result2 ، يصبح الكود حينها less readable بمعنى أصعب للفهم والتتبع واكتشاف الأخطاء وتطوير الكود مستقبلاً - احرص أن تكون الدالة الواحدة تقوم بوظيفة واحدة إن أمكن . . .

تم تعديل هذه المشاركة بواسطة namespace في 9 يوليو 2010 في 22:54

البرمجة = الرياضيات

#14

اهلا خالد

صح بس هو اختصرها لكن انا عادي ابغاها بالطريقه الي كتبتها عادي؟ ولا لازم اسوي بالضبط مثل ماسوا احمد؟

يعني يقوم بايجاد 3! و 5! ... الخ؟

مع ان المفروض في كلتا الحالتين يطلع نفس الجواب ، بس فعلا الماث مسوي ليا ازمه

الله يعين

#15

السلام عليكم

اقتباس
صح بس هو اختصرها لكن انا عادي ابغاها بالطريقه الي كتبتها عادي؟ ولا لازم اسوي بالضبط مثل ماسوا احمد؟

يعني يقوم بايجاد 3! و 5! ... الخ؟

كل ما في الأمر أنك ستقوم بحساب مضروب كل من 3 و 5 و 7 و 9 ثم تقوم بالتعويض.

اقتباس
مع ان المفروض في كلتا الحالتين يطلع نفس الجواب

الطريقة واحدة أخي الكريم و لايوجد اختلاف في النتائج.

بالنسبة للأخ namespace:

جاري كتابة الرد :wink:

تحياتي :)

#16

السلام عليكم

اقتباس
يمكن - لكن ليس كما فعلت أنت :lol:

:blush: :blush:

اقتباس
السطر التالي خارج الدوران مع أن الأصل أن يكون داخله ، لأن شرط الدوران يعتمد على n

معك حق :)

اقتباس
أليس الاستدعاء الذاتي ليغنينا عن الدوران ، أليس الاستدعاء الذاتي يفعل ما يعجز عنه الدوران ، وإلا فإن كان الأمر متاحاً بدوران بسيط فلم الاستدعاء الذاتي ؟

نعم و لكن لا ضير ان استخدمنا الدوران في الإستدعاء الذاتي فالأمر يتوقف على حاجتك أنت كمبرمج :wink: فأنت من يقرر استخدام أو عدم استخدام الدوران :cool:

في هذا التمرين سنحتاج إلى استخدام الدوران مع الإستدعاء الذاتي و بالمناسبة فإنك استخدمتَ الدوران مع الإستدعاء الذاتي في كل من sin,cos,tan :lol:

قمت بتغييرات في الكود بتاعي و هذا هو الكود الجديد:

float sin(float x,int r)
{
  int i=0,n=0;
  float result=0;
  while(n!=r)
  {
    if(x==0) result=1;
     else
     {
       if(++i%2!=0)
         result+=(x*sin(x,n-1)/n*sin(n-1));
        else
         result+=(-x*sin(x,n-1)/n*sin(n-1));
      }
       n+=2*n+1;
   }
  return result;
}

شرح الكود:

الدالة sin تستقبل متغيرين أحدهما float و الآخر int

بالنسبة لـ x فهي الزاوية المُراد حساب جيبها و المتغير r عبارة عن الأس الذي نتوقف عنده.

الهدف من المتغير i هو تغيير إشارة الجزء المُضاف للمجموع في كل مرة فإذا كان i فرديا فإننا نضع إشارة موجبة أمام المجموع أما إذا كان i زوجيا فإننا نضع إشارة سالبة أمام المجموع.

أما المتغير n فهو يمثل الأس في كل مرة و السبب في كتابة هذا السطر:

 n+=2*n+1;

لأن الأس فردي دائما , لاحظ أننا نتوقف عندما تكون n تساوي r أي أن المتغير n يمثل الأس المؤقت.

بانتظار تعليقاتكم على الكود الجديد :)

تم تعديل هذه المشاركة بواسطة khaled_prg في 9 يوليو 2010 في 23:47

#17

الحمدلله عرفت وين المشكله

لابد ان اجد قيمتهم اولا

3!=6

5!=120

7!=5040

9!=362880

بعدين اسوي كذا

sin(1)=1-1/6+1/120-1/5040+1/362880

وتطلع النتيجه صحيحه

اما اذا عملت الطريقه هذي sin(1) = 1 - 1^3/3*2*1 + 1^5/5*4*3*2*1

راح تتطلع القيمه ثانيه

#18

السلام عليكم

اقتباس
لابد ان اجد قيمتهم اولا

3!=6

5!=120

7!=5040

9!=362880

بعدين اسوي كذا

sin(1)=1-1/6+1/120-1/5040+1/362880

وتطلع النتيجه صحيحه

و هذا ما فعله الأخ أحمد و لكنك لم تنتبه :blink:

اقتباس
اما اذا عملت الطريقه هذي sin(1) = 1 - 1^3/3*2*1 + 1^5/5*4*3*2*1

راح تتطلع القيمه ثانيه

قم بحساب 3*2*1 و 5*4*3*2*1 حتى تصل إلى آخر كسر ثم قم بالتعويض و ستجد نفس النتيجة.

تحياتي.

#19

الان بقي سؤال اخر

16296156.jpg

ماعلاقه القانون هذا بالقوانين السابقه

khaled_prg كتب:

السلام عليكم

و هذا ما فعله الأخ أحمد و لكنك لم تنتبه :blink:

قم بحساب 3*2*1 و 5*4*3*2*1 حتى تصل إلى آخر كسر ثم قم بالتعويض و ستجد نفس النتيجة.

تحياتي.

اهلين خالد

صحيح كلامك وانا اعتقدت انها بتكون نفس النتيجه عشان كذا *_^

#20
empror9 كتب:

الان بقي سؤال اخر

16296156.jpg

ماعلاقه القانون هذا بالقوانين السابقه

هذا هو نفسه القوانين السابقة

لكن كل حد بدلالة الحدود التي تسبقه ، من هنا يمكن التفكير بالاستدعاء الذاتي أو recurtion

البرمجة = الرياضيات

#22
اقتباس
لأن الأس فردي دائما , لاحظ أننا نتوقف عندما تكون n تساوي r أي أن المتغير n يمثل الأس المؤقت.

بانتظار تعليقاتكم على الكود الجديد :)

في البداية يجب أن نضمن أن المستخدم أرسل قيمة r عدد فردي وليس زوجي كي لا نصل إلى دوران لانهائي

وذلك كالآتي : تضيف السطر التالي في بداية الاقتران

r=r/2*2+1;

ثم عليك الاختيار بين الدوران والاستدعاء الذاتي ، وليس كلاهما ، ما زلت مصراً على كلامي . .

هذا اقتران sin دون الحاجة إلى fact و pow

float sin(float x)
{
	float result = x;

	int limit = 10;
	int sign = -1;

	for(int i=3 ; i<limit ; i+=2,sign=-sign)
		result += sign*result*(x*x)/(i*(i-1));

	return result;
}

وهذا اقتران cos كذلك

float cos2(float x)
{
	float result = 1;

	int limit = 10;
	int sign = -1;

	for(int i=2 ; i<limit ; i+=2,sign=-sign)
		result += sign*result*(x*x)/(i*(i-1));

	return result;
}

قيمة result الجديدة تعتمد على السابقة كما أسلفنا ، وبهذا نستغني عن الاستدعاء الذاتي

.

تم تعديل هذه المشاركة بواسطة namespace في 10 يوليو 2010 في 11:24

البرمجة = الرياضيات

#23

السلام عليكم

اقتباس
في البداية يجب أن نضمن أن المستخدم أرسل قيمة r عدد فردي وليس زوجي كي لا نصل إلى دوران لانهائي

ملاحظة جيدة و أشكرك عليها :)

اقتباس
ثم عليك الاختيار بين الدوران والاستدعاء الذاتي ، وليس كلاهما ، ما زلت مصراً على كلامي . .

طيب .. إذا كان الحال هكذا فلماذا تستخدم الدوارة for داخل أكوادك !؟

بالنسبة للإستدعاء الذاتي فهل يمكن أن تعيد الدالة sin قيمة مثل :

x*sin(x,n-1)/n*sin(n-1)

يعني نستخدم الإستدعاء الذاتي مرتين :blink: :wacko:

اقتباس
هذا اقتران sin دون الحاجة إلى fact و pow

float sin(float x)
{
        float result = x;

        int limit = 10;
        int sign = -1;

        for(int i=3 ; i<limit ; i+=2,sign=-sign)
                result += sign*result*(x*x)/(i*(i-1));

        return result;
}

يا ريت تشرح الكود .. شكله صعب شويه :blink: :wacko:

تحياتي :)

#24

اهاا الله يسعدك ع المعلومه

طيب ممكن مثال بسيط عليه عشان افهمه بشكل اكثر؟ : $

#25
empror9 كتب:

طيب ممكن مثال بسيط عليه عشان افهمه بشكل اكثر؟

مثال على أي موضوع ؟

البرمجة = الرياضيات

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