برنامه نویسی، ریاضی ۹۸۳ بازدید

در آموزش‌های پیشین مجله فرادرس، با توابع بازگشتی آشنا شدیم. در این آموزش، مطالبی را درباره روش پیاده سازی توابع بازگشتی در پایتون بیان می‌کنیم.

تابع در ریاضیات

توابع مفاهیمی در ریاضیات و برنامه‌نویسی هستند که انجام برخی اعمال و دستورات را تسهیل می‌کنند.

توابع در ریاضیات چند مشخصه دارند:

  1. می‌توانند یک یا چند ورودی دریافت کنند.
  2. می‌توانند یک یا چند خروجی داشته باشند.
  3. می‌توانند روی ورودی‌ها اعمالی انجام داده و در خروجی برگردانند به شرطی که به ازای ورودی‌های یکسان همواره خروجی مشخصی تولید کنند.

برای مثال، $$f(x)=x^2$$ یک تابع با یک ورودی و یک خروجی است، در ضمن به ازای ورودی ثابت $$x$$ همواره مقدار $$x^2$$ را برمی‌گرداند.

تابع $$ f (x,y)=\frac x y $$ نیز یک تابع با دو ورودی و یک خروجی است.

برعکس موارد فوق، رابطه $$f(x,y)=x±y$$ یک تابع نیست، زیر به ازای برخی مقدایر از $$y$$ دو خروجی متمایز تولید می‌کند.

تابع در برنامه نویسی

اما در برنامه نویسی، مفهوم تابع اندکی متفاوت‌تر است:

1. یک تابع می‌تواند هیچ نوعی از ورودی نداشته باشد:

import time

def ReturnTime():
    return time.time()

۲. یک تابع می‌تواند هیچ نوعی از خروجی‌ نداشته باشد:

def PrintHorizentalLine():
    print('_'*50)

3. یک تابع می‌تواند با گرفتن ورودی‌های یکسان، خروجی‌های متفاوتی تولید کند:

import numpy as np

def SelectRandom(S:str):
    N = len(S)
    i = np.random.uniform(0,N)
    return S[i]

به این ترتیب، مشاهده می‌کنیم که توابع در برنامه‌نویسی می‌توانند برخی از مشخصه‌های توابع در ریاضیات را نداشته باشند.

برای یادگیری برنامه‌نویسی با زبان پایتون، پیشنهاد می‌کنیم به مجموعه آموزش‌های مقدماتی تا پیشرفته پایتون فرادرس مراجعه کنید که لینک آن در ادامه آورده شده است.

  • برای مشاهده مجموعه آموزش‌های برنامه نویسی پایتون (Python) — مقدماتی تا پیشرفته + اینجا کلیک کنید.

توابع بازگشتی در پایتون

توابع بازگشتی توابعی هستند که با گرفتن یک ورودی، می‌توانند پس از عملیاتی دوباره خود را فراخوانی کنند.

برای مثال تابع زیر پس از فراخوانی تا زمان بروی خطا، به چاپ کردن جمله Hello World ادامه خواهد داد:

def HW():
    print('Hello World')
    HW()

یا تابع زیر به ترتیب اعداد $$n$$ تا بی‌نهایت را چاپ خواهد کرد:

def Count(n:int):
    print(n)
    Count(n+1)

به این ترتیب، فراخوانی تابع توسط خودش مشهود است.

توابع بازگشتی چه کاربردی دارند؟

در ادامه، به برخی از کاربردهای توابع بازگشتی اشاره می‌کنیم.

فاکتوریل

فاکتوریل یک عدد صحیح به صورت زیر تعریف می‌شود:

$$ \large n !=n \times(n-1) \times(n-2) \ldots 2 \times 1, \quad 0 !=1 !=1 $$

برای پیاده‌سازی تابع فاکتوریل می‌توان به صورت زیر نوشت:

def Factorial(N:int):
    if N == 0 or N == 1:
        F = 1
    else:
        F = 1
        for i in range(1, N+1):
            F *= i
    return F

به این ترتیب، تابع مورد نظر کار خواهد کرد.

حال اندکی رابطه گفته‌شده را تغییر می‌دهیم:

$$ \large n !=n \times(n-1) \times(n-2) \ldots 2 \times 1=n \times(n-1) ! $$

به این ترتیب، می‌تواند فاکتوریل عدد $$n$$ را به فاکتوریل عدد $$n-1$$ ربط داد. از این ویژگی بازگشتی می‌توان به صورت زیر استفاده کرد:

def Factorial(N:int):
    if N == 0 or N == 1:
        return 1
    else:
        return N * Factorial(N-1)

به این ترتیب، پیاده‌سازی تابع مورد نظر در خطوط کمتر و به راحتی انجام می‌شود.

دنباله فیبوناچی

دنباله فیبوناچی به صورت زیر تعریف می‌شود:

$$ \large F_{n}=F_{n-1}+F_{n-2}, \quad F_{1}=F_{2}=1 $$

به این ترتیب، اگر بخواهیم این تابع را به شکل معمولی پیاده‌سازی کنیم خواهیم داشت:

def Fibonacci(N:int):
    if N == 1 or N == 2:
        F = 1
    else:
        a = 1
        b = 1
        for _ in range(N-2):
            F = a + b
            a = b
            b = F
    return F

حال اگر با استفاده از رابطه بازگشتی همین تابع را پیاده‌سازی کنیم خواهیم داشت:

def Fibonacci(N:int):
    if N == 1 or N == 2:
        return 1
    else:
        return Fibonacci(N-1) * Fibonacci(N-2)

به این ترتیب، مشاهده می‌کنیم که کدنویسی مورد نیاز برای توابع بازگشتی کمتر است و احتمال خطا نیز پایین است.

مورد فوق حالت‌های مربوط به پیاده‌سازی روابط ریاضی بودند. فرض کنید لیستی نامنظم و تودرتو به شکل زیر داریم:

$$ \large L=[1,2,[3,[4],[5], 6,7], 8,[[9]], 10] $$

و از ما خواسته شده است با نوشتن تابعی، لیست‌های داخلی را ساده کرده و در نهایت به یک لیست واحد برسیم. برای حل این مسئله به شکل توابع معمولی، نیاز به کدنویسی زیادی است و یک راه‌حل محتمل برای حل آن، استفاده از توابع بازگشتی است.

یک تابع برای ساده‌سازی این لیست می‌نویسم که در ورودی لیست مورد نظر را می‌گیرد:

def Simplify(L:list):

حال یک لیست خالی برای خروجی ایجاد می‌کنیم:

def Simplify(L:list):
    O = []

حال به ازای تک تک موارد داخل لیست ورودی، بررسی می‌کنیم که آیا یک عدد وجود دارد یا یک لیست:

def Simplify(L:list):
    O = []
    for i in L:
        if isinstance(i, int):

        else:

حال در صورت برقراری شرط، عضو مورد نظر را به لیست خروجی اضافه می‌کنیم و در صورت عدم برقراری شرط، خود تابع را بر روی عضو مورد نظر اعمال کرده و خروجی آن را به لیست خروجی اضافه می‌کنیم:

def Simplify(L:list):
    O = []
    for i in L:
        if isinstance(i, int):
            O.append(i)
        else:
            O.extend(Simplify(i))
    return O

به این ترتیب، تابع آماده است.

حال آن را بر روی لیست آورده شده اعمال می‌کنیم:

L = [1, 2, [3, [4], [5], 6, 7], 8, [[9]], 10]

L2 = Simplify(L)

print(L2)

و در خروجی به نتیجه زیر می‌رسیم:

$$ \large [1,2,3,4,5,6,7,8,9,10] $$

که خروجی مطلوب ما است.

معرفی فیلم آموزش محاسبات عددی در پایتون Python فرادرس

معرفی فیلم آموزش محاسبات عددی در پایتون Python فرادرس

آموزش محاسبات عددی در پایتون Python فرادرس در ۳ ساعت و ۱ دقیقه و در قالب ۷ درس تهیه و تدوین شده است. عناوین درس‌های این فیلم آموزشی، عبارت‌اند از: تعیین ریشه، درون‌یابی، مشتق‌گیری و انتگرال‌گیری عددی، حل عددی معادلات دیفرانسیل معمولی، حل عددی دستگاه معادلات خطی، مقادیر ویژه ماتریس‌ها و الگوریتم حداقل مربعات.

جمع‌بندی

در این آموزش، با توابع بازگشتی در پایتون آشنا شدیم و مثال‌های از آن را بررسی کردیم.

برای مطالعه بیشتر می‌توان موارد زیر را بررسی کرد:

  1. بیشترین دفعات ممکن برای Recursion
  2. اثر Recursion بر سرعت برنامه
  3. اثر حافظه و سرعت توابع بازگشتی
  4. مقایسه سرعت توابع بازگشتی با توابع معادل عادی
  5. ارتباط بین فراکتال‌ها (Fractals) و توابع بازگشتی

اگر این مطلب برای شما مفید بوده است، آموزش‌ها و مطالب زیر نیز به شما پیشنهاد می‌شوند:

بر اساس رای ۱۱ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

«سید علی کلامی هریس»، دانشجوی سال چهارم داروسازی دانشگاه علوم پزشکی تهران است. او در سال 1397 از دبیرستان «پروفسور حسابی» تبریز فارغ‌التحصیل شد و هم اکنون در کنار تحصیل در حوزه دارو‌سازی، به فعالیت در زمینه برنامه‌نویسی، یادگیری ماشین و تحلیل بازارهای مالی با استفاده از الگوریتم‌های هوشمند می‌پردازد.