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

أهمية الـshort circuiting عند كتابة الشروط

بدأه System Down في 4 مايو 2011 · 6 رد · 645 مشاهدة · في لغة Python
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

كما هو واضح من توقيعي أنا هذه الأيام أسلي نفسي بحل مسائل Project Euler، وهو أمر أنصح به الجميع لأنها طريقة رائعة (ومسلية) لتمرين مهارات حل المسائل وتعلم بعض المبادئ المتقدمة في البرمجة كما سنرى بعد قليل. قبل قليل كنت أحل المسألة رقم 44. اختصاراً لدينا متسلسلة حسابية بها عناصر لها معادلة رياضية معينة تدعي pentagonal. السؤال كان إيجاد رقمين ضمن هذه المتسلسلة يكون مجموعهما والفرق بينهما كلاهما أيضاً pentagonal. ومشي معي الحال. في المرة الأولى التي شغلت فيها البرنامج كتبت شرط إيجاد الحل داخل الـloop بهذا الشكل:

if (newP-oldP) in pentagonals and isP(newP+oldP):

الشطر الذي على اليسار يبحث عن فرق الرقمين داخل List بها الأعداد الـpentagonal التي تم حسابها مسبقاً. والشطر الذي على اليمين يقوم بنداء الدالة isP التي تقوم حسابياً بتحليل المجموع لمعرفة إذا كان يستوفي شروط متسلسلة pentagonal مقدماً. يجب طبعاً للحل استيفاء الشطرين. وبالفعل وجد البرنامج الحل في حوالي 101 ثانية. وهو رقم لا بأس به. ولكنني وضعت هدفاً لنفسي في جميع مسائل Euler أن يتم الحل في أقل من دقيقة. عندها تذكرت أن عملية البحث داخل List هي عملية مكلفة جداً إذا قارناها بالعمليات الحسابية الموجود داخل isP. وبما أنني وضعت عملية البحث في الشطر الأيسر فهذا يعني أن عملية البحث ستتم في كل iteration. وهذا مكلف فعلاً! ولكن لحسن الحظ فالجمل الشرطية في بايثون تدعم الـshort circuit. أي أنه في حال عدم استيفاء الشطر الأول من جملة الشرط فالمفسر لن ينفذ بقية الجملة. أي أنه إذا وضعت عملية isP الخفيفة أولاً فهذا يضمن أن عملية البحث الثقيلة لن تتم إلا إذا نجحت isP. وأصبح الكود:

if isP(newP+oldP) and (newP-oldP) in pentagonals:

النتيجة؟ البرنامج وجد الحل في 6.5 ثانية! أي تحسن 1580% في الأداء بمجرد قلب الشطرين. وهذا رقم كبير جداً! أعتقد أن هذا دليل جيد على أهمية معرفة كيف تعمل اللغة التي تستخدمها وراء الكواليس.

* ملاحظة: للفائدة وضعت البرنامج كاملاً كمرفق. ولو أنني أنصح الكل أن يحاول حل المسألة بنفسه قبل الاطلاع على الكود.

Euler044.py

تم تعديل هذه المشاركة بواسطة System Down في 4 مايو 2011 في 01:04

4
#2

موضوع جميل يا أخي ..

قرأت مرة أن filter is faster than filtering using for statement , إن كان صحيحاً فلم لم تستخدمها؟

سبحانك اللهم و بحمدك ، أشهد أن لا إله إلا أنت ، أستغفرك ربي و أتوب إليك

مدونتي

http://www.facebook.com/brmjt

#3
محمد سمير كتب:

موضوع جميل يا أخي ..

قرأت مرة أن filter is faster than filtering using for statement , إن كان صحيحاً فلم لم تستخدمها؟

لم يخطر على بالي صراحة. سأجربها وأرى.

#4

جربتها قبل قليل ولم أجد فرقاً كبيراً. استبدلت الـfor loop بهذه الجملة

result = [(newP, oldP) for oldP in pentagonals if isP(newP+oldP) and (newP-oldP) in pentagonals]
#5

بالمناسبة لماذا لم عرفت متغيرات لقيم ثابتة؟

def isP(number):
    x = (math.sqrt(24 * number + 1)+1)/6
    if x == int(x):
        return x
    else: return False

هكذا سيكون التنفيذ أسرع

سبحانك اللهم و بحمدك ، أشهد أن لا إله إلا أنت ، أستغفرك ربي و أتوب إليك

مدونتي

http://www.facebook.com/brmjt

#7
اقتباس
لم أفهم ماذا تقصد؟ تقصد cahce؟

عندك a و b ثوابت فعوضهم مباشرة بالمعادلة واضاف الى المعادلة الكود x = (-b+z)/(2*a)

طبعا وممكن الاستغناء عن جملة الشرط الاخيرة واستبدالها ب

return x == int(x)

ان امكن ذلك في بايثون

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