الهدف من المشروع هو برنامج يرسم الصيغ الرياضية، مثلاً يقول له المستخدمم س^2 + 5 فيرسم البرنامج شكل الـparabola المعروف.
- في الجزء الأول تحدثنا عن الإعراب، الدالة التي تأخذ نصاً مثل 12+13 وتعود بالمصفوفة ["+"، 12، 13] التي تمثل ما يسمى بشجرة الإعراب parse tree.
لو كنت قد قرأت الجزء الأول فأنت إذاً جاهز الآن لنختتم هذه السلسلة.
حساب قيمة التعبير
حسناً. لدينا الآن شجرة إعراب مثل 100 أو ["+"، س، 12]، ماذا نفعل بها؟ نريد دالة اسمها تقييم تأخذ الشجرة وتعود بالقيمة التي تعبر عنها.
- لو كانت "الشجرة" في صورة قيمة عددية، نعود بتلك القيمة.
- لو كانت الشجرة هي المتغير س (كقيمة نصية)، فإننا لا نستطيع أن نفعل شيئاً بأنفسنا، لذلك سوف نقدم عاملاً إضافياً parameter للدالة تقييم به قيمة س المطلوبة.
- لو كانت الشجرة في صورة مصفوفة مثل ["+"، أ، ب] سوف نقوم بالآتي:
- ناد الدالة تقييم مع الفرع الأيمن أ لحساب قيمته
- ناد الدالة أيضاً مع الفرع الأيسر ب
- نفذ العملية الحسابية وارجع بالنتيجة.
كل هذا يعطينا الكود التالية، الدالة تأخذ الشجرة "ت" وقيمة "س" المحددة من البرنامج، وتحسب قيمة الصيغة الرياضية:
دالة تقييم (ت، س): إذا ت ~ ["+"، ؟أ، ؟ب]: ارجع ب: تقييم (أ، س)+ تقييم (ب، س) وإلا إذا ت ~ ["-"، ؟أ، ؟ب]: ارجع ب: تقييم (أ، س)- تقييم (ب، س) وإلا إذا ت ~ ["×"، ؟أ، ؟ب]: ارجع ب: تقييم (أ، س)× تقييم (ب، س) وإلا إذا ت ~ ["÷"، ؟أ، ؟ب]: مقام = تقييم (ب، س) إذا مقام <> 0 : ارجع ب: تقييم (أ، س)÷ مقام وإلا : اطبع "خطأ: قسمة على صفر" ارجع ب: 0 تم وإلا إذا ت ~ ["^"، ؟أ، ؟ب]: ارجع ب: أس (تقييم (أ، س)، تقييم (ب، س)) وإلا إذا ت ~ "س" : ارجع ب: س وإلا : -- لو وصلنا إلى هنا فقيمة ت هي اصلا عدد ارجع ب: ت تم نهاية
لاحظ كيف استخدمنا مرة أخرى عملية المطابقة ~ لتسهيل الموضوع. الآن نحن جاهزون للرسم. أولاً نكتب إجراءاً مساعداً يرسم المحاور س، ص
إجراء ارسم.المحاور (): ارسم.خط (400، 0)- (400، 599) ارسم.خط (0، 300)- (799، 300) نهاية
الآن سوف نكتب الدالة التي ترسم فعلاً. خطتنا كالآتي:
الدالة سوف تأخذ عاملين: من.س و إلى.س، لكي نستطيع أن نقول مثلاً ارسم س^2 من س=-4 إلى س=4
سوف تقوم الدالة بالآتي:
- كرر بحيث يبدأ المتغير أ بالقيمة من.س وينتهي بالقيمة إلى.س، وكل مرة نضيف قيمة صغيرة إلى أ:
- احسب ص عن طريق استدعاء تقييم لحساب قيمة الصيغة الرياضية، واعطها قيمة المتغير س تساوي العداد أ
- سوف نرسم خطاً صغيراً بين كل نقطتين:
- لو كان هذا أول تكرار، فلا يوجد لدينا سوى نقطة واحدة. خزن قيمة أ في المتغير أ.قديم وقيمة ص في المتغير ص.قديم
- لو لم يكن أول تكرار، فنحن لدينا النقطة (أ، ص) والنقطة (أ.قديم، ص.قديم). سنرسم خطاً بينهما
هذا يعطينا الكود :
إجراء ارسم.الدالة (التعبير، من.س، إلى.س): أ = من.س أ.قديم = لاشيء ص.قديم = لاشيء مقياس.س = 20 مقياس.ص = 15 كرر مادام أ <= إلى.س : ص = تقييم (التعبير، أ) إذا ليس أ.قديم = لاشيء : س1 = - أ × مقياس.س + 400 ص1 = - ص × مقياس.ص + 300 س2 = - أ.قديم × مقياس.س + 400 ص2 = - ص.قديم × مقياس.ص + 300 ارسم.خط (س1، ص1)- (س2، ص2)، 4 تم أ.قديم = أ ص.قديم = ص أ = أ + 0.1 انتظر (30) تابع نهاية
لاحظ أننا نضرب الإحداثيات في بعض الثوابت ليكون لدينا مقياس رسم، وننتظر 30 مليثانية بين كل رسمة لكي نرى الدالة وهي تُرسم بسلاسة على الشاشة. لاحظ أن هذه الطريقة تفترض بعض الخصائص للدالة المطلوب رسمها (مثلاً أنها متصلة continuous).
لا يبقى إلا ان نربط كل المكونات ببعضها!
اقرأ "الصيغة؟"، الصيغة اقرأ "من؟"، # أ اقرأ "إلى؟"، # ب الصيغة = تبديل (الصيغة، " "، "") الشجرة = تعبير (الصيغة) ارسم.المحاور () ارسم.الدالة (الشجرة، أ، ب)
ماذا فعلنا؟
- قرأنا الصيغة من المستخدم (وقيم س التي سنبدأ وننتهي بها)
- حذفنا المسافات من الصيغة
- أعربناها لنحصل على شجرة الإعراب بواسطة الدالة تعبير
- رسمنا المحاور
- نادينا ارسم.الدالة وأعطيناها الشجرة وقيم من.س وإلى.س
- ارسم.الدالة سوف تنادي تقييم باستمرار لكي تحسب قيمة الصيغة عند كل قيمة لـ س
- ....وترسم الخطوط المطلوبة!
كم سطراً كتبنا؟ للأسف تجاوزنا حاجز المائة قليلاً: 109. لكن لو حذفنا السطور الفارغة بين تعريفات الدوال...الخ سيكون العدد أقل من المائة.
أقل من مائة سطر، تقوم بما قد يحتاج مئات الأسطر في لغات أخرى...
يمكنك عزيزي القاريء أن تجرب عمل نسخة متقدمة من البرنامج تضيف إمكانية استخدام الدوال مثل جتا، جا، أو تضيف الثابتين ط (π) و هـ (e) أوتقدم بعض المساعدة للمستخدم. لمَ لا تجرب؟ :)
ليست هناك تعليقات:
إرسال تعليق