سؤال

أدرك أن هذا قد يبدو وكأنه سؤال سخيف ، لكن في المرة الأخيرة التي قمت برمجتها في التجميع ، قد يكون تفكيري متوقفًا:

وظيفة عودية مثل:

def fac(n):
    if n == 0:
        return 1
    else:
        return n * fac(n - 1)

لماذا هو أنه عندما تصل الوظيفة إلى n == 0 ، فإنها لا تعود 1 بل الإجابة التي هي العازلة. أفكر في شيء مثل في المجمع ، سيكون عندما يكون n == 0:

mov eax, 1
ret

لماذا يعمل الرمز أعلاه ، أفترض أن Python يعيد القيمة الأخيرة على المكدس قبل هذا الشرط؟

هل كانت مفيدة؟

المحلول

فكر في مثل هذا ، ل fac(5) فمثلا:

return 5 * fac(4)
           return 4 * fac(3)
                      return 3 * fac(2)
                                 return 2 * fac(1)
                                            return 1 * fac(0)
                                                       1

لذا 1 سيكون ال أول القيمة التي تم إرجاعها ولكن سيتم إعادتها إلى fac(1) و fac(1) سيتم إعادته إلى fac(2) وهلم جرا.

نصائح أخرى

هو - هي يفعل إرجاع 1 عند n == 0. يتم برز قيمة الإرجاع هذه من موقع الاتصال ، والذي كان الاحتجاج في n * fac(n - 1). الذي - التي 1 مضروب من قبل n وعاد ، إلخ

إذا اتصلت بـ FAC (0) ، فسيعود 1 (وليس 0 ، لكنني أفترض أن هذا مجرد خطأ مطبعي في سؤالك). إذا اتصلت بـ FAC (1) ، فستذهب في الفقرة الأخرى ، وسيتصل بها fac(0). سيعود هذا 1. بعد ذلك سيحسب n*1 ، وهو 1 ، وإرجاع ذلك. إذا اتصلت fac(2) سوف يذهب أيضا في الفقرة الأخرى ، حيث سيتم الاتصال fac(1) ما هو مذكور أعلاه سيعود 1 ، لذلك n*fac(n-1) سيكون 2 وهذه هي قيمة الإرجاع fac(2). وهلم جرا. آمل أن شرح ذلك لك.

لا شيء يتم إرجاعه بشكل ضمني - عندما ن = 0 ، تدخل الوظيفة إلى البيان IF ، والعودة 1 مباشرة من return 1 بيان. ومع ذلك ، فإن هذه ليست النقطة التي يتم فيها إرجاع "الإجابة التي هي العامل" إلى المستخدم. بدلاً من ذلك ، قد يعيد هذه القيمة إلىالدعوة الوظيفة التي تم استدعاؤها بواسطة FAC (1) ، والتي في منتصف n * fac(n - 1) فرع. وبالتالي سوف يستغرق "1" عاد والعودة n*1, ، وهو 1 إلى إنه المتصل. إذا كان هذا هو الوجه (2) ، فسوف يعود n * 1, أو 2 إلى إنه المتصل وهلم جرا.

وهكذا يتم ترجمة FAC (5) مثل:

fac(5) = 5 * fac(4) = 5 * (4 * fac(3) = 5 * (4* (3 * fac(2)) = 5 * (4* (3 * (2 * fac(1)) = 5 * (4* (3 * (2 * (1 * fac(0)) = 5*4*3*2*1*1

فقط بعد إرجاع القيمة 1 من خلال كل طبقة علوية ، تعود إلى المتصل الأول ، ويمنحك الضرب في كل مرحلة الإجابة.

جيمس ، عندما تعيد المكالمة النهائية إلى وظيفتك (عند n == 0) ، فهي مجرد واحدة من عدة مثيلات من FAC (n) على مكدس الاتصال. إذا قلت الطباعة (FAC (4)) ، فإن المكدس هو بشكل أساسي:

fac(0)
fac(1)
fac(2)
fac(3)
fac(4)
print()

إرجاع المكالمة النهائية لـ FAC (0) بشكل مناسب 1 ، ولكن في Python ، طلبت قيمة الإرجاع للمكالمة الأولى لـ FAC (N) ، FAC (4).

لا تفكر في الأمر كحلقة حيث ستندلع "Ret" ، فإن العودة ببساطة تختتم واحدة من العديد من عمليات الإعدام المعلقة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top