آموزش پایتون, تمرین و پروژه‌های پایتون

پروژه ساخت ماشین‌حساب ساده با پایتون؛ آموزش مرحله‌به‌مرحله

پروژه ساخت ماشین‌حساب ساده با پایتون

🗓 آخرین به‌روزرسانی:

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

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

در این پروژه چه چیزی می‌سازیم؟

ماشین‌حساب نهایی قابلیت‌های زیر را خواهد داشت:

  • دریافت دو عدد از کاربر
  • انجام جمع، تفریق، ضرب و تقسیم
  • پشتیبانی از تقسیم صحیح، باقی‌مانده و توان
  • تشخیص عملگر نامعتبر
  • جلوگیری از تقسیم بر صفر
  • مدیریت ورودی غیرعددی
  • تکرار محاسبه تا انتخاب گزینه خروج
  • ذخیره و نمایش تاریخچه محاسبات

پیش‌نیازهای پروژه

برای انجام این پروژه بهتر است با موضوع‌های زیر آشنا باشید:

  • تابع print()
  • متغیرها و انواع داده
  • تابع input()
  • تبدیل ورودی با float()
  • عملگرهای ریاضی و مقایسه‌ای
  • شرط‌های if، elif و else
  • حلقه while
  • دستورهای break و continue
  • لیست و متد append()
  • مدیریت خطا با try و except

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

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

first_number = float(input("عدد اول را وارد کنید: "))
second_number = float(input("عدد دوم را وارد کنید: "))

result = first_number + second_number
print("حاصل جمع:", result)

اگر کاربر عددهای ۱۲ و ۸ را وارد کند، خروجی چنین خواهد بود:

عدد اول را وارد کنید: 12
عدد دوم را وارد کنید: 8
حاصل جمع: 20.0

از float() استفاده کرده‌ایم تا برنامه هم عددهای صحیح و هم اعشاری را بپذیرد.

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

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

first_number = float(input("عدد اول: "))
operator = input("عملگر را وارد کنید (+، -، *، /): ").strip()
second_number = float(input("عدد دوم: "))

متغیر operator یک رشته متنی است و مقدارهایی مانند + یا * را نگهداری می‌کند.

مرحله سوم: تصمیم‌گیری با if و elif

براساس عملگر انتخاب‌شده، محاسبه مناسب را انجام می‌دهیم:

first_number = float(input("عدد اول: "))
operator = input("عملگر را وارد کنید (+، -، *، /): ").strip()
second_number = float(input("عدد دوم: "))

if operator == "+":
    result = first_number + second_number
elif operator == "-":
    result = first_number - second_number
elif operator == "*":
    result = first_number * second_number
elif operator == "/":
    result = first_number / second_number
else:
    result = "عملگر نامعتبر است."

print("نتیجه:", result)

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

مشکل تقسیم بر صفر

نسخه فعلی در صورت تقسیم بر صفر با خطای ZeroDivisionError متوقف می‌شود:

10 / 0

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

elif operator == "/":
    if second_number == 0:
        result = "تقسیم بر صفر امکان‌پذیر نیست."
    else:
        result = first_number / second_number

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

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

عملگرکاربردمثال
+جمع8 + 2
-تفریق8 - 2
*ضرب8 * 2
/تقسیم معمولی9 / 2
//تقسیم صحیح9 // 2
%باقی‌مانده9 % 2
**توان2 ** 3
if operator == "+":
    result = first_number + second_number
elif operator == "-":
    result = first_number - second_number
elif operator == "*":
    result = first_number * second_number
elif operator == "/":
    if second_number == 0:
        result = "تقسیم بر صفر امکان‌پذیر نیست."
    else:
        result = first_number / second_number
elif operator == "//":
    if second_number == 0:
        result = "تقسیم بر صفر امکان‌پذیر نیست."
    else:
        result = first_number // second_number
elif operator == "%":
    if second_number == 0:
        result = "محاسبه باقی‌مانده با مقسوم‌علیه صفر ممکن نیست."
    else:
        result = first_number % second_number
elif operator == "**":
    result = first_number ** second_number
else:
    result = "عملگر نامعتبر است."

مرحله پنجم: مدیریت ورودی غیرعددی

اگر کاربر به‌جای عدد عبارت متنی وارد کند، تابع float() خطای ValueError ایجاد می‌کند. با try و except می‌توان این خطا را کنترل کرد:

try:
    first_number = float(input("عدد اول: "))
    second_number = float(input("عدد دوم: "))
except ValueError:
    print("لطفاً فقط عدد معتبر وارد کنید.")

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

مرحله ششم: اجرای چندباره ماشین‌حساب

برای اینکه کاربر بتواند چند محاسبه انجام دهد، کل برنامه را داخل حلقه while True قرار می‌دهیم:

while True:
    print("\nماشین‌حساب پایتون")
    print("برای خروج، q را وارد کنید.")

    first_input = input("عدد اول: ").strip()

    if first_input.lower() == "q":
        print("برنامه بسته شد.")
        break

    # ادامه دریافت اطلاعات و انجام محاسبه

اگر کاربر حرف q را وارد کند، دستور break حلقه را پایان می‌دهد.

نسخه کامل ماشین‌حساب ساده با پایتون

کد زیر تمام بخش‌های پروژه را کنار هم قرار می‌دهد:

history = []

while True:
    print("\n" + "=" * 35)
    print("ماشین‌حساب ساده پایتون")
    print("عملگرها: +  -  *  /  //  %  **")
    print("برای خروج q و برای تاریخچه h را وارد کنید.")
    print("=" * 35)

    first_input = input("عدد اول: ").strip()

    if first_input.lower() == "q":
        print("خروج از ماشین‌حساب")
        break

    if first_input.lower() == "h":
        if len(history) == 0:
            print("تاریخچه هنوز خالی است.")
        else:
            print("\nتاریخچه محاسبات:")
            for index, item in enumerate(history, start=1):
                print(index, item)
        continue

    try:
        first_number = float(first_input)
    except ValueError:
        print("خطا: عدد اول معتبر نیست.")
        continue

    operator = input("عملگر: ").strip()

    if operator not in ["+", "-", "*", "/", "//", "%", "**"]:
        print("خطا: عملگر واردشده پشتیبانی نمی‌شود.")
        continue

    second_input = input("عدد دوم: ").strip()

    try:
        second_number = float(second_input)
    except ValueError:
        print("خطا: عدد دوم معتبر نیست.")
        continue

    if operator == "+":
        result = first_number + second_number
    elif operator == "-":
        result = first_number - second_number
    elif operator == "*":
        result = first_number * second_number
    elif operator == "/":
        if second_number == 0:
            print("خطا: تقسیم بر صفر امکان‌پذیر نیست.")
            continue
        result = first_number / second_number
    elif operator == "//":
        if second_number == 0:
            print("خطا: تقسیم بر صفر امکان‌پذیر نیست.")
            continue
        result = first_number // second_number
    elif operator == "%":
        if second_number == 0:
            print("خطا: محاسبه باقی‌مانده با صفر ممکن نیست.")
            continue
        result = first_number % second_number
    else:
        result = first_number ** second_number

    calculation = f"{first_number} {operator} {second_number} = {result}"
    history.append(calculation)

    print("نتیجه:", result)

بررسی مرحله‌به‌مرحله نسخه کامل

۱. ساخت تاریخچه

history = []

یک لیست خالی می‌سازیم تا هر محاسبه موفق در آن ذخیره شود.

۲. ساخت حلقه اصلی

while True:

برنامه تا زمانی ادامه پیدا می‌کند که کاربر گزینه خروج را انتخاب کند.

۳. بررسی فرمان‌های q و h

فرمان q برای خروج و h برای نمایش تاریخچه در نظر گرفته شده است. متد lower() باعث می‌شود حروف بزرگ و کوچک انگلیسی تفاوتی نداشته باشند.

۴. تبدیل ورودی به عدد

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

۵. اعتبارسنجی عملگر

if operator not in ["+", "-", "*", "/", "//", "%", "**"]:

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

۶. جلوگیری از تقسیم بر صفر

برای عملگرهای /، // و % باید عدد دوم غیرصفر باشد. در غیر این صورت پیام خطا نمایش داده می‌شود.

۷. ذخیره نتیجه

calculation = f"{first_number} {operator} {second_number} = {result}"
history.append(calculation)

محاسبه به یک رشته خوانا تبدیل و به انتهای فهرست تاریخچه اضافه می‌شود.

نمونه اجرای برنامه

===================================
ماشین‌حساب ساده پایتون
عملگرها: +  -  *  /  //  %  **
برای خروج q و برای تاریخچه h را وارد کنید.
===================================
عدد اول: 12
عملگر: *
عدد دوم: 4
نتیجه: 48.0

نمونه تقسیم بر صفر:

عدد اول: 10
عملگر: /
عدد دوم: 0
خطا: تقسیم بر صفر امکان‌پذیر نیست.

نمونه نمایش تاریخچه:

عدد اول: h

تاریخچه محاسبات:
1 12.0 * 4.0 = 48.0
2 20.0 + 5.0 = 25.0

چرا از eval استفاده نکردیم؟

ممکن است نمونه‌هایی ببینید که عبارت واردشده توسط کاربر را مستقیماً با تابع eval() اجرا می‌کنند. استفاده مستقیم از eval() روی ورودی کاربر می‌تواند کد ناخواسته یا خطرناک را اجرا کند. برای یک ماشین‌حساب آموزشی و امن‌تر، بهتر است عملگرهای مجاز را صریحاً بررسی و هر محاسبه را خودمان پیاده‌سازی کنیم.

بهبود نمایش عددهای صحیح

در نسخه فعلی، چون ورودی‌ها با float() تبدیل می‌شوند، نتیجه‌هایی مانند ۲۰ به شکل 20.0 نمایش داده می‌شوند. می‌توان پیش از نمایش بررسی کرد که نتیجه بخش اعشاری دارد یا خیر:

if isinstance(result, float) and result.is_integer():
    result = int(result)

این بخش را می‌توانید درست پیش از ساخت متغیر calculation قرار دهید.

خطاهای رایج در پروژه

استفاده از یک مساوی در شرط

if operator = "+":  # نادرست

برای مقایسه باید از == استفاده شود.

فراموش‌کردن تبدیل ورودی

first_number = input("عدد اول: ")

خروجی input() رشته است. برای محاسبات باید آن را با float() یا int() تبدیل کرد.

تقسیم بدون بررسی صفر

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

قرار دادن continue پیش از پیام خطا

اگر continue زودتر اجرا شود، دستورهای پس از آن در همان دور اجرا نخواهند شد. بنابراین پیام خطا باید پیش از continue قرار گیرد.

تورفتگی نادرست

کدهای داخل حلقه و شرط‌ها باید تورفتگی یکسان و صحیح داشته باشند. ترکیب Tab و فاصله نیز می‌تواند باعث خطا شود.

تمرین‌های توسعه پروژه

  1. عملگر جذر را با توان 0.5 اضافه کنید.
  2. گزینه‌ای برای پاک‌کردن تاریخچه بسازید.
  3. تعداد محاسبات موفق را نمایش دهید.
  4. امکان استفاده از نتیجه قبلی به‌عنوان عدد اول را اضافه کنید.
  5. برای عملگرها یک منوی شماره‌دار طراحی کنید.
  6. نتیجه را تا دو رقم اعشار گرد کنید.
  7. کمترین و بیشترین نتیجه موجود در تاریخچه را پیدا کنید.
  8. برای ورودی خالی پیام اختصاصی نمایش دهید.
  9. ماشین‌حساب را طوری تغییر دهید که سه عدد دریافت کند.
  10. پس از یادگیری توابع، هر عملیات را داخل یک تابع جداگانه قرار دهید.

چک‌لیست آزمایش ماشین‌حساب

پیش از پایان پروژه، حالت‌های زیر را آزمایش کنید:

  • جمع دو عدد صحیح
  • ضرب دو عدد اعشاری
  • تقسیم بر عدد غیرصفر
  • تقسیم بر صفر
  • ورود متن به‌جای عدد
  • ورود عملگر نامعتبر
  • نمایش تاریخچه خالی
  • نمایش تاریخچه پس از چند محاسبه
  • خروج با حرف بزرگ یا کوچک Q

📌 همچنین بخوانید: بازار کار پایتون در ایران، تمرین پایتون با جواب و ساخت بازی با پایتون و Pygame

پرسش‌های متداول

چرا برای عددها از float استفاده شده است؟

زیرا float() هم عددهای صحیح و هم اعشاری را می‌پذیرد. در نتیجه ماشین‌حساب محدود به عددهای صحیح نیست.

چرا ماشین‌حساب داخل while True قرار دارد؟

تا برنامه پس از هر محاسبه بسته نشود و کاربر بتواند چند عملیات انجام دهد. خروج از حلقه با دستور break کنترل می‌شود.

آیا استفاده از eval برای ماشین‌حساب مناسب است؟

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

چگونه رابط گرافیکی برای ماشین‌حساب بسازیم؟

پس از تسلط بر مبانی و توابع می‌توانید با کتابخانه‌هایی مانند Tkinter نسخه گرافیکی بسازید. این پروژه فعلاً روی منطق برنامه تمرکز دارد.

چرا نتیجه جمع دو عدد صحیح به‌صورت اعشاری نمایش داده می‌شود؟

چون هر دو ورودی با float() تبدیل شده‌اند. می‌توانید با بررسی result.is_integer() نتیجه‌های بدون بخش اعشاری را به int تبدیل کنید.

جمع‌بندی پروژه

در این پروژه یک برنامه واقعی ساختیم که از کاربر ورودی می‌گیرد، نوع داده را تبدیل می‌کند، با شرط‌ها تصمیم می‌گیرد، محاسبات مختلف انجام می‌دهد، خطاها را کنترل می‌کند، تاریخچه را داخل لیست نگه می‌دارد و با حلقه while چند بار اجرا می‌شود.

تکمیل این پروژه نشان می‌دهد مفاهیم اصلی بخش مقدماتی پایتون را می‌توانید در کنار یکدیگر به کار ببرید. بهترین تمرین این است که ابتدا نسخه ساده را خودتان بنویسید و سپس قابلیت‌های نسخه کامل را مرحله‌به‌مرحله اضافه کنید.

← درس قبلی: لیست‌ها در پایتون

بازگشت به فهرست کامل دوره آموزش پایتون

ادامه مسیر یادگیری پایتون

برای یادگیری منظم، آموزش‌های مرتبط زیر را به‌ترتیب دنبال کنید:

می‌خواهی پیشرفتت ذخیره شود؟با ورود یا ثبت‌نام رایگان، درس‌های تمام‌شده را علامت بزن و درصد پیشرفتت را در حساب کاربری ببین.ورود / ثبت‌نام برای ذخیره پیشرفت
آموزش‌های تازه، کد آماده و رفع خطاهر هفته در کانال Dev Source؛ رایگان.
🧭 مسیر یادگیری پایتون از صفر
ماژول 4: رشته‌ها و لیست‌ها — درس 18 از 44

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

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *