第26课:简易计算器升级版——带错误处理的四则运算
🎯 本课目标
- 综合运用条件判断知识
- 掌握程序错误处理方法
- 学会使用try-except捕获异常
- 处理除零等特殊情况
- 制作可连续运算的智能计算器
🤔 趣味引入:计算器的"烦恼"
想象一下:计算器也会遇到"烦恼":
- ➗ 除以0 → "不能除以0啊!"
- 📝 输入字母 → "这不是数字!"
- 🔢 数字太大 → "超出范围了!"
- 🔄 连续运算 → "接下来算什么?"
今天,让我们一起升级计算器,让它变得"聪明"又"友好"!
🔧 第一部分:错误处理基础
1.1 什么是错误处理?
# 错误处理基础
print("🎯 认识错误处理")
print("=" * 50)
print("""
程序运行时可能遇到的错误:
1. ValueError:输入的值类型不对
2. ZeroDivisionError:除以0
3. TypeError:类型错误
4. NameError:变量未定义
5. IndexError:索引超出范围
使用try-except来"抓住"错误:
try:
可能会出错的代码
except 错误类型:
出错时执行的代码
""")
# 没有错误处理的程序
print("❌ 没有错误处理:")
try:
num = int(input("请输入一个数字:"))
result = 10 / num
print(f"10 ÷ {num} = {result}")
except ValueError:
print("❌ 输入的不是数字!")
except ZeroDivisionError:
print("❌ 不能除以0!")
except Exception as e:
print(f"❌ 发生了错误:{e}")
print("\n✅ 程序安全地继续执行...")
1.2 try-except详解
# try-except详解
print("\n📚 try-except语法详解")
print("=" * 50)
print("""
📋 基本语法:
try:
# 尝试执行的代码
可能出错的语句
except 错误类型1:
# 发生错误类型1时执行
处理代码
except 错误类型2:
# 发生错误类型2时执行
处理代码
else:
# 没有错误时执行
成功后的代码
finally:
# 无论是否出错都会执行
清理代码
""")
# 完整示例
print("\n🎬 完整示例:")
def safe_divide(a, b):
"""安全除法"""
try:
result = a / b
except ZeroDivisionError:
return "❌ 除数不能为0!"
except TypeError:
return "❌ 请输入数字!"
else:
return f"✅ {a} ÷ {b} = {result}"
finally:
print(" 计算完成")
# 测试
print(safe_divide(10, 2))
print(safe_divide(10, 0))
print(safe_divide(10, "a"))
🧮 第二部分:基础计算器升级
2.1 带错误处理的四则运算
# 带错误处理的四则运算
print("\n🧮 带错误处理的计算器")
print("=" * 50)
def add(a, b):
"""加法"""
return a + b
def subtract(a, b):
"""减法"""
return a - b
def multiply(a, b):
"""乘法"""
return a * b
def divide(a, b):
"""除法(带错误处理)"""
if b == 0:
return "❌ 不能除以0!"
return a / b
def calculate(num1, operator, num2):
"""执行计算"""
if operator == "+":
return add(num1, num2)
elif operator == "-":
return subtract(num1, num2)
elif operator == "*":
return multiply(num1, num2)
elif operator == "/":
return divide(num1, num2)
else:
return "❌ 不支持的运算符!"
# 交互式计算器
print("欢迎使用智能计算器!")
print("支持运算:+、-、*、/")
print("输入'quit'退出\n")
while True:
try:
# 获取用户输入
expression = input("请输入算式(如:5 + 3):")
if expression.lower() == "quit":
print("👋 感谢使用!再见!")
break
# 分割算式
parts = expression.split()
if len(parts) != 3:
print("❌ 格式错误!请按'数字 运算符 数字'格式输入")
continue
num1 = float(parts[0])
operator = parts[1]
num2 = float(parts[2])
# 执行计算
result = calculate(num1, operator, num2)
# 显示结果
if isinstance(result, str):
print(result)
else:
# 如果是整数,显示整数形式
if result == int(result):
print(f"✅ {num1} {operator} {num2} = {int(result)}")
else:
print(f"✅ {num1} {operator} {num2} = {result:.2f}")
except ValueError:
print("❌ 请输入有效的数字!")
except Exception as e:
print(f"❌ 发生了意外错误:{e}")
2.2 增强版计算器
# 增强版计算器
print("\n🚀 增强版计算器")
print("=" * 50)
class Calculator:
"""计算器类"""
def __init__(self):
self.history = []
self.last_result = 0
self.memory = 0
def add(self, a, b):
"""加法"""
result = a + b
self._record(f"{a} + {b} = {result}")
return result
def subtract(self, a, b):
"""减法"""
result = a - b
self._record(f"{a} - {b} = {result}")
return result
def multiply(self, a, b):
"""乘法"""
result = a * b
self._record(f"{a} × {b} = {result}")
return result
def divide(self, a, b):
"""除法"""
if b == 0:
raise ZeroDivisionError("除数不能为0!")
result = a / b
self._record(f"{a} ÷ {b} = {result}")
return result
def power(self, a, b):
"""幂运算"""
result = a ** b
self._record(f"{a}^{b} = {result}")
return result
def modulo(self, a, b):
"""取余"""
if b == 0:
raise ZeroDivisionError("除数不能为0!")
result = a % b
self._record(f"{a} % {b} = {result}")
return result
def _record(self, record):
"""记录计算历史"""
self.history.append(record)
self.last_result = float(record.split("=")[-1].strip())
def show_history(self):
"""显示历史记录"""
if not self.history:
return "📋 暂无计算记录"
result = "📋 计算历史:\n"
result += "-" * 30 + "\n"
for i, record in enumerate(self.history[-10:], 1):
result += f"{i}. {record}\n"
result += "-" * 30
return result
def clear_history(self):
"""清除历史"""
self.history = []
self.last_result = 0
return "✅ 历史已清除"
def memory_store(self):
"""存入记忆"""
self.memory = self.last_result
return f"💾 已存储:{self.memory}"
def memory_recall(self):
"""取出记忆"""
return f"📤 取出记忆:{self.memory}"
def memory_clear(self):
"""清除记忆"""
self.memory = 0
return "✅ 记忆已清除"
# 使用增强版计算器
calc = Calculator()
print("欢迎使用增强版计算器!")
print("支持运算:+、-、*、/、^(幂)、%(取余)")
print("特殊命令:")
print(" history - 查看历史")
print(" ms - 存入记忆")
print(" mr - 取出记忆")
print(" mc - 清除记忆")
print(" clear - 清除历史")
print(" quit - 退出\n")
while True:
try:
command = input("请输入:").strip().lower()
# 处理特殊命令
if command == "quit":
print("👋 感谢使用!再见!")
break
elif command == "history":
print(calc.show_history())
continue
elif command == "ms":
print(calc.memory_store())
continue
elif command == "mr":
print(calc.memory_recall())
continue
elif command == "mc":
print(calc.memory_clear())
continue
elif command == "clear":
print(calc.clear_history())
continue
# 解析算式
parts = command.split()
if len(parts) == 3:
num1 = float(parts[0])
operator = parts[1]
num2 = float(parts[2])
# 执行计算
if operator == "+":
result = calc.add(num1, num2)
elif operator == "-":
result = calc.subtract(num1, num2)
elif operator == "*":
result = calc.multiply(num1, num2)
elif operator == "/":
result = calc.divide(num1, num2)
elif operator == "^":
result = calc.power(num1, num2)
elif operator == "%":
result = calc.modulo(num1, num2)
else:
print("❌ 不支持的运算符!")
continue
# 显示结果
if result == int(result):
print(f"✅ 结果:{int(result)}")
else:
print(f"✅ 结果:{result:.4f}")
elif len(parts) == 2 and parts[0] == "ans":
# 使用上一次结果继续计算
operator = parts[1]
num2 = float(input("输入第二个数字:"))
if operator == "+":
result = calc.add(calc.last_result, num2)
elif operator == "-":
result = calc.subtract(calc.last_result, num2)
elif operator == "*":
result = calc.multiply(calc.last_result, num2)
elif operator == "/":
result = calc.divide(calc.last_result, num2)
else:
print("❌ 不支持的运算符!")
continue
if result == int(result):
print(f"✅ 结果:{int(result)}")
else:
print(f"✅ 结果:{result:.4f}")
else:
print("❌ 格式错误!请按'数字 运算符 数字'格式输入")
except ValueError:
print("❌ 请输入有效的数字!")
except ZeroDivisionError as e:
print(f"❌ {e}")
except Exception as e:
print(f"❌ 发生了错误:{e}")
🎯 第三部分:高级计算器功能
3.1 科学计算器
# 科学计算器
print("\n🔬 科学计算器")
print("=" * 50)
import math
class ScientificCalculator(Calculator):
"""科学计算器类"""
def sqrt(self, a):
"""平方根"""
if a < 0:
raise ValueError("负数没有平方根!")
result = math.sqrt(a)
self._record(f"√{a} = {result}")
return result
def sin(self, a):
"""正弦(角度制)"""
result = math.sin(math.radians(a))
self._record(f"sin({a}°) = {result}")
return result
def cos(self, a):
"""余弦(角度制)"""
result = math.cos(math.radians(a))
self._record(f"cos({a}°) = {result}")
return result
def tan(self, a):
"""正切(角度制)"""
if a % 180 == 90:
raise ValueError("tan(90°)不存在!")
result = math.tan(math.radians(a))
self._record(f"tan({a}°) = {result}")
return result
def log(self, a, base=10):
"""对数"""
if a <= 0:
raise ValueError("对数参数必须大于0!")
if base <= 0 or base == 1:
raise ValueError("底数必须大于0且不等于1!")
result = math.log(a, base)
self._record(f"log_{base}({a}) = {result}")
return result
def ln(self, a):
"""自然对数"""
if a <= 0:
raise ValueError("自然对数参数必须大于0!")
result = math.log(a)
self._record(f"ln({a}) = {result}")
return result
def factorial(self, a):
"""阶乘"""
if a < 0:
raise ValueError("负数没有阶乘!")
if a != int(a):
raise ValueError("阶乘只支持整数!")
result = math.factorial(int(a))
self._record(f"{int(a)}! = {result}")
return result
def abs(self, a):
"""绝对值"""
result = abs(a)
self._record(f"|{a}| = {result}")
return result
def round_to(self, a, decimals):
"""四舍五入"""
result = round(a, decimals)
self._record(f"round({a}, {decimals}) = {result}")
return result
# 使用科学计算器
sci_calc = ScientificCalculator()
print("欢迎使用科学计算器!")
print("支持的运算:")
print(" 基础:+、-、*、/、^、%")
print(" 科学:sqrt、sin、cos、tan、log、ln、!")
print(" 其他:abs、round")
print(" 特殊:ans(上次结果)、pi(π)")
print(" 命令:history、ms、mr、mc、clear、quit\n")
while True:
try:
command = input("请输入:").strip().lower()
if command == "quit":
print("👋 感谢使用!再见!")
break
elif command == "history":
print(sci_calc.show_history())
continue
elif command in ["ms", "mr", "mc", "clear"]:
if command == "ms":
print(sci_calc.memory_store())
elif command == "mr":
print(sci_calc.memory_recall())
elif command == "mc":
print(sci_calc.memory_clear())
elif command == "clear":
print(sci_calc.clear_history())
continue
# 替换特殊常量
command = command.replace("pi", str(math.pi))
command = command.replace("π", str(math.pi))
command = command.replace("ans", str(sci_calc.last_result))
parts = command.split()
if len(parts) == 1:
# 一元运算
func = parts[0]
if func.startswith("sqrt"):
num = float(func[4:].strip("()"))
result = sci_calc.sqrt(num)
elif func.startswith("sin"):
num = float(func[3:].strip("()"))
result = sci_calc.sin(num)
elif func.startswith("cos"):
num = float(func[3:].strip("()"))
result = sci_calc.cos(num)
elif func.startswith("tan"):
num = float(func[3:].strip("()"))
result = sci_calc.tan(num)
elif func.startswith("log"):
params = func[3:].strip("()").split(",")
if len(params) == 1:
num = float(params[0])
result = sci_calc.log(num)
else:
num = float(params[0])
base = float(params[1])
result = sci_calc.log(num, base)
elif func.startswith("ln"):
num = float(func[2:].strip("()"))
result = sci_calc.ln(num)
elif func.endswith("!"):
num = float(func[:-1])
result = sci_calc.factorial(num)
elif func.startswith("abs"):
num = float(func[3:].strip("()"))
result = sci_calc.abs(num)
else:
print("❌ 不支持的函数!")
continue
print(f"✅ 结果:{result:.6f}")
elif len(parts) == 3:
# 二元运算
num1 = float(parts[0])
operator = parts[1]
num2 = float(parts[2])
if operator == "+":
result = sci_calc.add(num1, num2)
elif operator == "-":
result = sci_calc.subtract(num1, num2)
elif operator == "*":
result = sci_calc.multiply(num1, num2)
elif operator == "/":
result = sci_calc.divide(num1, num2)
elif operator == "^":
result = sci_calc.power(num1, num2)
elif operator == "%":
result = sci_calc.modulo(num1, num2)
else:
print("❌ 不支持的运算符!")
continue
if result == int(result):
print(f"✅ 结果:{int(result)}")
else:
print(f"✅ 结果:{result:.6f}")
else:
print("❌ 格式错误!")
except ValueError as e:
print(f"❌ {e}")
except ZeroDivisionError as e:
print(f"❌ {e}")
except Exception as e:
print(f"❌ 发生了错误:{e}")
3.2 表达式计算器
# 表达式计算器
print("\n📝 表达式计算器")
print("=" * 50)
def evaluate_expression(expression):
"""安全计算表达式"""
# 允许的字符
allowed_chars = set("0123456789+-*/(). ")
# 检查是否包含非法字符
for char in expression:
if char not in allowed_chars and not char.isalpha():
return None, "包含非法字符!"
try:
# 使用eval但限制命名空间
result = eval(expression, {"__builtins__": {}}, {})
return result, None
except ZeroDivisionError:
return None, "不能除以0!"
except SyntaxError:
return None, "表达式语法错误!"
except Exception as e:
return None, f"计算错误:{e}"
def format_result(result):
"""格式化结果"""
if result is None:
return "❌ 无法计算"
if isinstance(result, float):
if result == int(result):
return f"✅ = {int(result)}"
else:
return f"✅ = {result:.4f}"
else:
return f"✅ = {result}"
print("欢迎使用表达式计算器!")
print("支持:加减乘除、括号、小数")
print("示例:")
print(" (5 + 3) * 2")
print(" 10 / (4 - 2)")
print(" 3.5 * 2 + 1")
print("输入'quit'退出\n")
while True:
expression = input("请输入表达式:").strip()
if expression.lower() == "quit":
print("👋 感谢使用!再见!")
break
if not expression:
continue
result, error = evaluate_expression(expression)
if error:
print(f"❌ {error}")
else:
print(format_result(result))
📊 第四部分:计算器综合应用
4.1 财务计算器
# 财务计算器
print("\n💰 财务计算器")
print("=" * 50)
class FinanceCalculator:
"""财务计算器类"""
def calculate_interest(self, principal, rate, years):
"""计算利息"""
if principal <= 0:
raise ValueError("本金必须大于0!")
if rate < 0 or rate > 100:
raise ValueError("利率必须在0-100之间!")
if years <= 0:
raise ValueError("年限必须大于0!")
rate_decimal = rate / 100
total = principal * (1 + rate_decimal * years)
interest = total - principal
return {
"principal": principal,
"rate": rate,
"years": years,
"interest": interest,
"total": total
}
def calculate_compound_interest(self, principal, rate, years, times_per_year=12):
"""计算复利"""
if principal <= 0:
raise ValueError("本金必须大于0!")
if rate < 0 or rate > 100:
raise ValueError("利率必须在0-100之间!")
if years <= 0:
raise ValueError("年限必须大于0!")
rate_decimal = rate / 100
total = principal * (1 + rate_decimal / times_per_year) ** (times_per_year * years)
interest = total - principal
return {
"principal": principal,
"rate": rate,
"years": years,
"times_per_year": times_per_year,
"interest": interest,
"total": total
}
def calculate_discount(self, original_price, discount_percent):
"""计算折扣"""
if original_price <= 0:
raise ValueError("原价必须大于0!")
if discount_percent < 0 or discount_percent > 100:
raise ValueError("折扣率必须在0-100之间!")
discount_amount = original_price * discount_percent / 100
final_price = original_price - discount_amount
return {
"original_price": original_price,
"discount_percent": discount_percent,
"discount_amount": discount_amount,
"final_price": final_price
}
def calculate_tax(self, income, tax_rate):
"""计算税费"""
if income < 0:
raise ValueError("收入不能为负!")
if tax_rate < 0 or tax_rate > 100:
raise ValueError("税率必须在0-100之间!")
tax = income * tax_rate / 100
after_tax = income - tax
return {
"income": income,
"tax_rate": tax_rate,
"tax": tax,
"after_tax": after_tax
}
def split_bill(self, total, people, tip_percent=0):
"""分摊账单"""
if total <= 0:
raise ValueError("总额必须大于0!")
if people <= 0:
raise ValueError("人数必须大于0!")
if tip_percent < 0:
raise ValueError("小费比例不能为负!")
tip = total * tip_percent / 100
grand_total = total + tip
per_person = grand_total / people
return {
"total": total,
"people": people,
"tip_percent": tip_percent,
"tip": tip,
"grand_total": grand_total,
"per_person": per_person
}
# 使用财务计算器
finance = FinanceCalculator()
print("欢迎使用财务计算器!")
print("请选择功能:")
print("1. 💰 计算利息(单利)")
print("2. 📈 计算复利")
print("3. 🏷️ 计算折扣")
print("4. 📋 计算税费")
print("5. 👥 分摊账单")
print("0. 🚪 退出")
while True:
try:
choice = input("\n请选择(0-5):")
if choice == "0":
print("👋 感谢使用!再见!")
break
elif choice == "1":
p = float(input("本金(元):"))
r = float(input("年利率(%):"))
y = float(input("存款年限:"))
result = finance.calculate_interest(p, r, y)
print(f"\n📊 利息计算结果:")
print(f" 本金:{result['principal']:.2f}元")
print(f" 利率:{result['rate']}%")
print(f" 年限:{result['years']}年")
print(f" 利息:{result['interest']:.2f}元")
print(f" 本息合计:{result['total']:.2f}元")
elif choice == "2":
p = float(input("本金(元):"))
r = float(input("年利率(%):"))
y = float(input("存款年限:"))
t = int(input("每年复利次数(默认12):") or "12")
result = finance.calculate_compound_interest(p, r, y, t)
print(f"\n📊 复利计算结果:")
print(f" 本金:{result['principal']:.2f}元")
print(f" 利率:{result['rate']}%")
print(f" 年限:{result['years']}年")
print(f" 复利次数:{result['times_per_year']}次/年")
print(f" 利息:{result['interest']:.2f}元")
print(f" 本息合计:{result['total']:.2f}元")
elif choice == "3":
p = float(input("原价(元):"))
d = float(input("折扣率(%,如打8折输入20):"))
result = finance.calculate_discount(p, d)
print(f"\n📊 折扣计算结果:")
print(f" 原价:{result['original_price']:.2f}元")
print(f" 折扣:{result['discount_percent']}%")
print(f" 优惠:{result['discount_amount']:.2f}元")
print(f" 实付:{result['final_price']:.2f}元")
print(f" 节省:{result['discount_amount']:.2f}元")
elif choice == "4":
income = float(input("收入(元):"))
rate = float(input("税率(%):"))
result = finance.calculate_tax(income, rate)
print(f"\n📊 税费计算结果:")
print(f" 税前收入:{result['income']:.2f}元")
print(f" 税率:{result['tax_rate']}%")
print(f" 缴税:{result['tax']:.2f}元")
print(f" 税后收入:{result['after_tax']:.2f}元")
elif choice == "5":
total = float(input("账单总额(元):"))
people = int(input("分摊人数:"))
tip = float(input("小费比例(%,可选0):") or "0")
result = finance.split_bill(total, people, tip)
print(f"\n📊 账单分摊结果:")
print(f" 账单总额:{result['total']:.2f}元")
print(f" 分摊人数:{result['people']}人")
print(f" 小费:{result['tip']:.2f}元")
print(f" 总计:{result['grand_total']:.2f}元")
print(f" 每人应付:{result['per_person']:.2f}元")
else:
print("❌ 请选择0-5!")
except ValueError as e:
print(f"❌ {e}")
except Exception as e:
print(f"❌ 发生了错误:{e}")
📅 下节课预告
第27课:年龄判断机——判断年龄段并提供不同建议
下节课你将学习:
- 综合运用条件判断和嵌套
- 设计多年龄段判断逻辑
- 根据不同年龄给出建议
- 制作完整的年龄分析系统
- 处理生日和年龄计算
预习思考:
- 人生可以分为哪些年龄段?
- 不同年龄段有什么特点?
- 如何根据年龄给出贴心建议?
💬 给家长的话
亲爱的家长:
今天孩子学习了错误处理,这是编写健壮程序的重要技能。通过这门课,孩子学会了如何让程序优雅地处理各种意外情况。
孩子今天学会了:
- ✅ 使用try-except捕获错误
- ✅ 处理除零等特殊情况
- ✅ 制作带错误处理的计算器
- ✅ 实现连续运算和记忆功能
- ✅ 开发财务计算等实用工具
错误处理的教育价值:
| 能力 | 在编程中的应用 | 培养价值 |
|------|---------------|---------|
| 预见性 | 预判可能的错误 | 风险意识 |
| 容错性 | 优雅处理错误 | 抗压能力 |
| 调试能力 | 定位和修复bug | 问题解决 |
| 用户体验 | 友好的错误提示 | 同理心 |
| 健壮性 | 程序稳定运行 | 可靠性 |
您可以这样做:
生活应用:
- 预算计算:用财务计算器管理零花钱
- 购物比价:用折扣计算器算优惠
- 账单分摊:和朋友AA制算账
- 理财启蒙:用利息计算器学习理财
温馨提示:
- 错误处理让程序更"聪明"
- 鼓励孩子思考"可能出什么问题"
- 友好的错误提示很重要
- 通过实际应用加深理解
🏆 今日成就
完成了今天的学习,你:
🛡️ 学会了错误处理
🧮 升级了计算器
💰 制作了财务工具
🔬 开发了科学计算
📝 实现了表达式计算
挑战任务:
- 添加更多科学计算功能
- 制作图形界面计算器
- 实现计算历史持久化
- 添加单位换算功能
🌟 编程心法
程序如人生
难免遇到错误
学会处理异常
才能走得更远
try是尝试的勇气
except是包容的胸怀
else是成功的喜悦
finally是始终的坚持
让每一个错误
都成为进步的阶梯
让每一次异常
都化作成长的养分
这才是编程的智慧
也是人生的哲理
记住:错误不可怕,可怕的是不知道怎么处理错误。学会错误处理,你的程序才能真正"长大成人"!
第26课结束。你现在已经是一个会"容错"的编程高手了!
实践任务:
1. 完善计算器功能
2. 制作个人财务工具
3. 添加更多科学函数
4. 优化用户体验
下节课,让我们学习年龄判断,了解不同年龄段的特点!
第27课见!🎂