Python 中数字:整数、浮点数完全指南
本文档面向零基础新手,详细讲解 整数(int) 和 浮点数(float) 的用法,并说明为什么会出现 0.1 + 0.2 ≠ 0.3 这类现象,以及如何用 decimal 和 fractions 模块解决或避免这类问题。
第一部分:整数(int)
一、整数是什么?
整数 就是没有小数部分的数,可以是正数、负数或零。在 Python 里类型名是 int(integer 的缩写)。
a = 10
b = -5
c = 0
print(type(a), type(b), type(c)) # <class 'int'> <class 'int'> <class 'int'>
二、整数的写法
- 直接写数字,不能有小数点
- 可以加正负号
- 数字中间不能有逗号(如
1,000在 Python 里是错的,要写1000)
age = 18
count = -100
big = 1000000
zero = 0
三、整数的运算
| 运算符 | 含义 | 示例 |
|---|---|---|
+ |
加法 | 10 + 3 → 13 |
- |
减法 | 10 - 3 → 7 |
* |
乘法 | 10 * 3 → 30 |
/ |
除法 | 10 / 3 → 3.333…(结果是 float) |
// |
整除 | 10 // 3 → 3(只保留整数部分) |
% |
取余数 | 10 % 3 → 1 |
** |
乘方 | 10 ** 2 → 100 |
示例:
a, b = 10, 3
print(a + b) # 13
print(a - b) # 7
print(a * b) # 30
print(a / b) # 3.3333333333333335(注意:结果是浮点数)
print(a // b) # 3(整除)
print(a % b) # 1(余数)
print(a ** b) # 1000(10 的 3 次方)
整除与取余的常见用途:
# 判断奇偶
n = 7
print(n % 2 == 0) # False,7 是奇数
print(8 % 2 == 0) # True,8 是偶数
# 取个位、十位
num = 123
ge = num % 10 # 个位 3
shi = num // 10 % 10 # 十位 2
bai = num // 100 # 百位 1
print(ge, shi, bai) # 3 2 1
四、整数的类型转换
用 int() 可以把其他类型转成整数:
- 浮点数转整数:直接截断小数部分(不四舍五入)
- 字符串转整数:字符串必须是“整数的写法”
print(int(3.9)) # 3(截断,不是 4)
print(int(-3.9)) # -3
print(int("100")) # 100
# print(int("3.14")) # 报错:不能直接转带小数点的字符串
# print(int("abc")) # 报错:不是合法数字
第二部分:浮点数(float)
五、浮点数是什么?
浮点数 就是带小数点的数,用来表示小数。在 Python 里类型名是 float。
x = 3.14
y = -0.5
z = 2.0
print(type(x)) # <class 'float'>
六、浮点数的写法
- 带小数点:
3.14、0.5、2.0 - 科学计数法:
1.5e2表示 1.5×10² = 150.0,2e-3表示 2×10⁻³ = 0.002
a = 3.14
b = 1.5e2 # 150.0
c = 2e-3 # 0.002
print(a, b, c) # 3.14 150.0 0.002
七、浮点数的运算
运算符和整数一样:+、-、*、/、//、%、**。只要参与运算的数里有浮点数,结果一般是浮点数。
print(10.0 + 3) # 13.0
print(10 / 3) # 3.3333333333333335
print(2.5 ** 2) # 6.25
八、浮点数转整数 / 字符串转浮点数
# 浮点 → 整数(截断)
print(int(3.14)) # 3
# 字符串 → 浮点
print(float("3.14")) # 3.14
print(float("1.5e2")) # 150.0
第三部分:为什么 0.1 + 0.2 ≠ 0.3?
九、现象
在 Python 里你会看到:
print(0.1 + 0.1) # 0.2
print(0.1 + 0.2) # 0.30000000000000004
print(0.2 + 0.1) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
为什么 0.1 + 0.1 得到 0.2,而 0.1 + 0.2 却得到 0.30000000000000004?
十、原因简述(不用记细节,知道“会误差”即可)
- 电脑用 二进制 存数,而我们写的是 十进制。
- 很多十进制小数(如 0.1、0.2)在二进制里是无限循环小数,无法精确表示。
- 浮点数只能用有限位来存,所以会四舍五入/截断,产生微小误差。
- 0.1、0.2 存进去时都已经有微小误差;相加时误差可能“露出来”,所以 0.1 + 0.2 显示成 0.30000000000000004。
- 0.1 + 0.1 刚好在当前的表示方式下误差被“抵消”或舍入成 0.2,所以看起来是 0.2。
结论: 这不是 Python 的 bug,而是浮点数在计算机里的通病。做金额、精确小数时不要直接用 float,而要用下面说的 decimal 或 fractions。
第四部分:方法一 —— 使用 decimal 模块(推荐)
十一、decimal 是什么?
decimal 是 Python 自带的模块,提供 Decimal 类型,用十进制来存和算,可以控制小数位数和舍入方式,适合金额、精确小数。
十二、基本用法
步骤:
- 导入模块:
from decimal import Decimal - 用 Decimal(“数字”) 创建数(建议用字符串,避免先把 0.1 变成 float 再转成 Decimal 又把误差带进来)
- 之后加减乘除和整数、浮点数类似
from decimal import Decimal
a = Decimal("0.1")
b = Decimal("0.2")
c = a + b
print(c) # 0.3
print(c == Decimal("0.3")) # True
print(c == 0.3) # False
为什么推荐用字符串?
# 不推荐:用浮点数构造,会把浮点误差带进来
a = Decimal(0.1)
print(a) # 0.1000000000000000055511151231257827021181583404541015625
# 推荐:用字符串
a = Decimal("0.1")
print(a) # 0.1
十三、设置小数位数和舍入方式:getcontext()
用 decimal 模块里的 getcontext() 可以设置精度(有效数字位数)和舍入方式。
from decimal import Decimal, getcontext
# 设置保留 2 位小数(用于金额)
getcontext().prec = 6 # 有效数字位数(可选)
getcontext().rounding = "ROUND_HALF_UP" # 四舍五入(可选)
a = Decimal("1.234")
b = Decimal("2.345")
c = a + b
print(c) # 3.579
保留固定小数位:quantize()
from decimal import Decimal, ROUND_HALF_UP
price = Decimal("19.567")
# 保留 2 位小数,四舍五入
price = price.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(price) # 19.57
常用舍入模式(了解即可):
ROUND_HALF_UP:四舍五入(0.5 向上)ROUND_HALF_DOWN:0.5 向下ROUND_FLOOR:向负无穷取整ROUND_CEILING:向正无穷取整
十四、decimal 示例汇总
示例 1:精确的 0.1 + 0.2
from decimal import Decimal
a = Decimal("0.1")
b = Decimal("0.2")
print(a + b) # 0.3
示例 2:金额计算(保留 2 位小数)
from decimal import Decimal, ROUND_HALF_UP
单价 = Decimal("19.99")
数量 = 3
总价 = 单价 * 数量
总价 = 总价.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print("总价:", 总价) # 总价: 59.97
示例 3:和整数、字符串混用
from decimal import Decimal
a = Decimal("10.5")
b = 2
print(a * b) # 21.0(Decimal 和 int 可以运算)
第五部分:方法二 —— 使用 fractions 模块(适合分数运算)
十五、fractions 是什么?
fractions 是 Python 自带的模块,提供 Fraction 类型,用分子/分母的方式表示有理数,适合分数运算(如 1/3 + 1/6),结果可以保持为分数形式,避免浮点误差。
十六、Fraction 详细解释
16.1 什么是 Fraction?
Fraction 表示一个分数,即 分子/分母。例如 1/2、1/3、-2/5。
内部会自动约分,所以存储和运算都是精确的分数,不会出现 0.1+0.2 那种误差。
16.2 创建 Fraction
方式一:Fraction(分子, 分母)
from fractions import Fraction
a = Fraction(1, 2) # 1/2
b = Fraction(3, 4) # 3/4
print(a) # 1/2
print(b) # 3/4
方式二:Fraction(整数)
表示“整数/1”。
c = Fraction(5) # 5/1,即 5
print(c) # 5
方式三:Fraction(字符串)
字符串可以是 “1/2″、”0.5″、”3.14” 等。
d = Fraction("1/2") # 1/2
e = Fraction("0.25") # 1/4
f = Fraction("3.14") # 157/50(自动转成最简分数)
print(d, e, f)
方式四:Fraction(浮点数) 或 Fraction(Decimal)
从浮点数或 Decimal 构造。注意:从 float 构造时,会先把 float 转成分数,可能带有浮点误差。
# 从 float:可能不精确
g = Fraction(0.1)
print(g) # 3602879701896397/36028797018963968(不是简单的 1/10)
# 从字符串更稳妥
h = Fraction("0.1")
print(h) # 1/10
小结: 想要精确分数时,优先用 整数分子分母 或 字符串(如 "1/3"、"0.1"),少用 Fraction(0.1) 这种从 float 构造的方式。
16.3 Fraction 的属性:分子和分母
用 .numerator 和 .denominator 可以取出分子、分母(都是整数,且已约分到最简)。
from fractions import Fraction
a = Fraction(3, 6) # 自动约分为 1/2
print(a) # 1/2
print(a.numerator) # 1
print(a.denominator) # 2
16.4 Fraction 的运算
支持 +、-、*、/、** 等,结果仍是 Fraction(或整数),保持精确。
from fractions import Fraction
a = Fraction(1, 3)
b = Fraction(1, 6)
print(a + b) # 1/2
print(a - b) # 1/6
print(a * b) # 1/18
print(a / b) # 2
与整数、浮点数运算时,会得到 Fraction 或 float(根据类型提升规则)。
print(Fraction(1, 2) + 1) # 3/2
print(Fraction(1, 2) + 0.5) # 1.0(float)
16.5 转成小数或字符串
- float(Fraction):转成浮点数(可能又有浮点误差)
- str(Fraction):如
"1/2"、"3"
from fractions import Fraction
a = Fraction(1, 3)
print(float(a)) # 0.3333333333333333
print(str(a)) # 1/3
16.6 从浮点数构造:Fraction.from_float() / Fraction.from_decimal()
- Fraction.from_float(x):等价于
Fraction(x),把 float 转成“最接近的”分数,可能分母很大。 - Fraction.from_decimal(d):从 Decimal 转成 Fraction,若 Decimal 是精确的,Fraction 也精确。
from fractions import Fraction
from decimal import Decimal
# 从 float
f = Fraction.from_float(0.1)
print(f) # 3602879701896397/36028797018963968
# 从 Decimal(推荐)
d = Decimal("0.1")
f = Fraction.from_decimal(d)
print(f) # 1/10
十七、Fraction 示例汇总
示例 1:精确的 1/3 + 1/6
from fractions import Fraction
a = Fraction(1, 3)
b = Fraction(1, 6)
print(a + b) # 1/2
示例 2:避免 0.1 + 0.2 的误差
from fractions import Fraction
a = Fraction("0.1") # 1/10
b = Fraction("0.2") # 1/5
c = a + b
print(c) # 3/10
print(float(c)) # 0.3
示例 3:分数运算后取分子分母
from fractions import Fraction
x = Fraction(7, 12) + Fraction(1, 12)
print(x) # 2/3
print(x.numerator) # 2
print(x.denominator) # 3
第六部分:decimal 和 fractions 怎么选?
| 场景 | 建议 |
|---|---|
| 金额、价格、保留几位小数 | 用 decimal(方便 quantize 控制小数位) |
| 分数运算、比例、精确有理数 | 用 fractions(Fraction) |
| 一般科学计算、对误差不敏感 | 用 float 即可 |
可以混用: 例如用 Decimal 算金额,需要时再转成 Fraction 或 float。
第七部分:小结表
| 类型/模块 | 用途 | 注意 |
|---|---|---|
| int | 整数 | / 得到 float;// 整除,% 取余 |
| float | 小数 | 有精度误差,金额/精确小数慎用 |
| Decimal | 精确十进制小数 | 建议 Decimal("0.1") 用字符串构造 |
| Fraction | 精确分数 | 建议用 Fraction(1,3) 或 Fraction("0.1"),少用 Fraction(0.1) |
为什么 0.1+0.1=0.2 而 0.1+0.2≠0.3?
浮点数用二进制存储,0.1、0.2 无法精确表示,有微小误差;不同组合下误差有时被舍入掉(像 0.2),有时会显示出来(如 0.30000000000000004)。
解决办法: 金额/精确小数用 decimal;分数、比例用 fractions(Fraction)。