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

🗓 آخرین بهروزرسانی:
در این پروژه، آموختههای دوره را کنار هم قرار میدهیم و یک ماشینحساب ساده اما کاربردی با پایتون میسازیم. برنامه از کاربر دو عدد و یک عملگر دریافت میکند، محاسبه را انجام میدهد، خطاهای رایج را مدیریت میکند و تا زمانی که کاربر بخواهد دوباره اجرا میشود.
این مطلب، پروژه پایانی بخش مقدماتی دوره رایگان آموزش پایتون از صفر است. در درس قبلی با لیستها آشنا شدیم. اکنون متغیرها، ورودی کاربر، انواع داده، عملگرها، شرطها، حلقهها و مدیریت اولیه خطا را در یک برنامه واقعی ترکیب میکنیم.
در این پروژه چه چیزی میسازیم؟
ماشینحساب نهایی قابلیتهای زیر را خواهد داشت:
- دریافت دو عدد از کاربر
- انجام جمع، تفریق، ضرب و تقسیم
- پشتیبانی از تقسیم صحیح، باقیمانده و توان
- تشخیص عملگر نامعتبر
- جلوگیری از تقسیم بر صفر
- مدیریت ورودی غیرعددی
- تکرار محاسبه تا انتخاب گزینه خروج
- ذخیره و نمایش تاریخچه محاسبات
پیشنیازهای پروژه
برای انجام این پروژه بهتر است با موضوعهای زیر آشنا باشید:
- تابع
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 و فاصله نیز میتواند باعث خطا شود.
تمرینهای توسعه پروژه
- عملگر جذر را با توان
0.5اضافه کنید. - گزینهای برای پاککردن تاریخچه بسازید.
- تعداد محاسبات موفق را نمایش دهید.
- امکان استفاده از نتیجه قبلی بهعنوان عدد اول را اضافه کنید.
- برای عملگرها یک منوی شمارهدار طراحی کنید.
- نتیجه را تا دو رقم اعشار گرد کنید.
- کمترین و بیشترین نتیجه موجود در تاریخچه را پیدا کنید.
- برای ورودی خالی پیام اختصاصی نمایش دهید.
- ماشینحساب را طوری تغییر دهید که سه عدد دریافت کند.
- پس از یادگیری توابع، هر عملیات را داخل یک تابع جداگانه قرار دهید.
چکلیست آزمایش ماشینحساب
پیش از پایان پروژه، حالتهای زیر را آزمایش کنید:
- جمع دو عدد صحیح
- ضرب دو عدد اعشاری
- تقسیم بر عدد غیرصفر
- تقسیم بر صفر
- ورود متن بهجای عدد
- ورود عملگر نامعتبر
- نمایش تاریخچه خالی
- نمایش تاریخچه پس از چند محاسبه
- خروج با حرف بزرگ یا کوچک Q
📌 همچنین بخوانید: بازار کار پایتون در ایران، تمرین پایتون با جواب و ساخت بازی با پایتون و Pygame
پرسشهای متداول
چرا برای عددها از float استفاده شده است؟
زیرا float() هم عددهای صحیح و هم اعشاری را میپذیرد. در نتیجه ماشینحساب محدود به عددهای صحیح نیست.
چرا ماشینحساب داخل while True قرار دارد؟
تا برنامه پس از هر محاسبه بسته نشود و کاربر بتواند چند عملیات انجام دهد. خروج از حلقه با دستور break کنترل میشود.
آیا استفاده از eval برای ماشینحساب مناسب است؟
برای ورودی کنترلنشده کاربر توصیه نمیشود. بررسی صریح عملگرها خواناتر، آموزشیتر و امنتر است.
چگونه رابط گرافیکی برای ماشینحساب بسازیم؟
پس از تسلط بر مبانی و توابع میتوانید با کتابخانههایی مانند Tkinter نسخه گرافیکی بسازید. این پروژه فعلاً روی منطق برنامه تمرکز دارد.
چرا نتیجه جمع دو عدد صحیح بهصورت اعشاری نمایش داده میشود؟
چون هر دو ورودی با float() تبدیل شدهاند. میتوانید با بررسی result.is_integer() نتیجههای بدون بخش اعشاری را به int تبدیل کنید.
جمعبندی پروژه
در این پروژه یک برنامه واقعی ساختیم که از کاربر ورودی میگیرد، نوع داده را تبدیل میکند، با شرطها تصمیم میگیرد، محاسبات مختلف انجام میدهد، خطاها را کنترل میکند، تاریخچه را داخل لیست نگه میدارد و با حلقه while چند بار اجرا میشود.
تکمیل این پروژه نشان میدهد مفاهیم اصلی بخش مقدماتی پایتون را میتوانید در کنار یکدیگر به کار ببرید. بهترین تمرین این است که ابتدا نسخه ساده را خودتان بنویسید و سپس قابلیتهای نسخه کامل را مرحلهبهمرحله اضافه کنید.
بازگشت به فهرست کامل دوره آموزش پایتون
ادامه مسیر یادگیری پایتون
برای یادگیری منظم، آموزشهای مرتبط زیر را بهترتیب دنبال کنید:
برای ذخیره پیشرفت در همه دستگاهها و دریافت گواهی پایان مسیر، رایگان ثبتنام کن یا وارد شو.