Python 练习讲解 · 21 / 25

整数、有理数与实数

认识数系关系,并比较精确分数与浮点小数的计算方式。

要学习的知识点

题目

补充练习:自然数、整数、有理数、实数及加减乘除。

输入:一行整数 n;一行两个分数(如 1/2 3/4);一行两个实数。

参考程序:ex21.py;空白练习:lx21.py。

完整代码

以下内容与 ex21.py 一致,可对照右侧讲解阅读。

"""补充练习:自然数、整数、有理数、实数及加减乘除。
输入:一行整数 n;一行两个分数(如 1/2 3/4);一行两个实数。

学习说明:
- 数系逐层包含:整数是有理数的一部分,有理数又属于实数;本练习将 0 也算作自然数。
- Fraction 可以精确保存分数,例如 1/2 + 1/3 会得到 5/6,而不是近似小数。
- float 表示常见十进制小数,计算结果可能有少量二进制浮点误差。
- 分别输出加、减、乘、除;除法前先判断除数是否为 0。
"""
from fractions import Fraction

n = int(input())
# Fraction 接收形如 1/2 的分数字符串;float 接收小数。
rational_a, rational_b = map(Fraction, input().split())
real_a, real_b = map(float, input().split())

print("integer:", n)
print("is natural (including 0):", n >= 0)
print("integer is also rational and real:", True)
print("rational type:", type(rational_a).__name__)
print("real approximation type:", type(real_a).__name__)

print("rational + - *:", rational_a + rational_b, rational_a - rational_b,
        rational_a * rational_b)
if rational_b != 0:
      print("rational /:", rational_a / rational_b)
else:
      print("rational /: undefined when divisor is 0")
print("real + - *:", real_a + real_b, real_a - real_b, real_a * real_b)
if real_b != 0:
      print("real /:", real_a / real_b)
else:
      print("real /: undefined when divisor is 0")

进阶写法

这版与初学版解决同一道题,使用更精炼的语法或标准库工具。

进阶源码:ex21_adv.py

"""练习 21 进阶版:用 map 一次转换分数行和实数行。"""
from fractions import Fraction

n = int(input())
rational_a, rational_b = map(Fraction, input().split())
real_a, real_b = map(float, input().split())

print("integer:", n)
print("is natural (including 0):", n >= 0)
print("integer is also rational and real:", True)
print("rational type:", type(rational_a).__name__)
print("real approximation type:", type(real_a).__name__)
print("rational + - *:", rational_a + rational_b, rational_a - rational_b, rational_a * rational_b)
print("rational /:", rational_a / rational_b if rational_b else "undefined when divisor is 0")
print("real + - *:", real_a + real_b, real_a - real_b, real_a * real_b)
print("real /:", real_a / real_b if real_b else "undefined when divisor is 0")

map(Fraction, ...) 和 map(float, ...) 分别逐项构造精确分数和浮点数;条件表达式只在除数非零时执行除法。

运行结果

示例输入:

-2
1/2 3/4
1.5 2.5

程序输出:

integer: -2
is natural (including 0): False
integer is also rational and real: True
rational type: Fraction
real approximation type: float
rational + - *: 5/4 -1/4 3/8
rational /: 2/3
real + - *: 4.0 -1.0 3.75
real /: 0.6

逐个认识函数

下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。

函数形式功能与返回值注意事项
input(prompt='')读取一行文本,返回 str;若提供 prompt 会先显示提示。返回值默认是字符串,计算前通常要做类型转换。
str.split(sep=None)按分隔符拆分字符串,返回字符串列表。默认按连续空白拆分并忽略首尾空白。
int(value, base=10)把整数文本或数值转换为整数。int('3.5') 不合法;按指定进制解析时可传 base。
map(function, iterable)逐个应用函数,返回惰性迭代器。常与 list() 一起使用以立即取得结果。
print(*objects, sep=' ', end='\n')把对象转换为文本显示;返回 None。默认空格分隔并在末尾换行。
type(obj)返回对象的类型对象。可用 type(obj).__name__ 取得易读的类型名称。

数系关系

自然数(本程序约定包含 0)属于整数;整数也可以写成分母为 1 的有理数;有理数和无理数共同组成实数。示意:自然数 ⊂ 整数 ⊂ 有理数 ⊂ 实数。

对应示例 ex21.py:输入整数 n、两个分数文本、两个小数,分别执行四则运算。

Fraction 类与内置函数

函数/方法参数与返回值注意事项
Fraction(text)fractions 模块的构造函数;可从 "1/2" 形式文本构造精确有理数。导入方式为 from fractions import Fraction。不要先把小数转 float 再构造分数,否则会保留浮点近似。
float(text)内置函数,把数字文本转换为浮点数。浮点数按二进制保存,部分十进制小数不能精确表示。
int(input())读取一行字符串并转成整数。本题只据 n>=0 判断自然数;不同教材可能把自然数定义为从 1 开始。
type(value).__name__显示对象类型名。Fraction 对象的类型名是 Fraction;实数输入变量是 float。
print(...)输出给定对象;返回 None。只是展示结果,不会把文本当作计算值返回。

四则运算与零除数

整数、有理数、浮点数都能使用 + - * /。Fraction 运算会自动约分,例如 1/2 + 1/3 得精确的 5/6;float 运算输出小数近似。

from fractions import Fraction
first = Fraction("1/2")
second = Fraction("1/3")
print(first + second)  # 5/6
print(0.1 + 0.2)       # 浮点近似值,并非数学上的精确 0.3

除法的除数为 0 时没有定义,Python 会抛 ZeroDivisionError。本程序用 if rational_b != 0、if real_b != 0 先检查。

输入细节

分数行必须像 1/2 3/4,而不是两个分开的输入行;input().split() 拆开它,map 再把每个文本交给 Fraction 构造。实数行形如 1.5 2.5,通过 map(float, ...) 转换。

将分数输入 1/3 与 1/3,将小数输入 0.1 与 0.2,对比输出精度差异。

代码如何运行

  1. 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
  2. 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
  3. 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。

先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。

自己动手试一试

输入 1/3 与 1/3、0.1 与 0.2;比较 Fraction 的精确结果和 float 的近似结果。

先在 lx21.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。