浮点数 float
Python 的 float 类型采用 IEEE 754 双精度标准(64 位),提供约 15-17 位有效数字的精度。它适合科学计算,但用于金融计算时需要格外谨慎。
创建浮点数
浮点数字面量包含小数点或指数部分:
pi = 3.14159
temperature = -273.15
zero_float = 0.0
科学计数法用 e 或 E 表示乘以 10 的幂:
print(1.5e2) # 150.0
print(1.5e-2) # 0.015
print(6.022e23) # 6.022 × 10²³
print(1e308) # 1e+308,接近最大值
float() 构造函数可从字符串或数字转换:
print(float("3.14")) # 3.14
print(float(" 2.5 ")) # 2.5
print(float(42)) # 42.0
非法格式会抛出 ValueError:
print(float("")) # ValueError
print(float("abc")) # ValueError
print(float("3.14.15")) # ValueError
精度问题
浮点数用二进制表示小数,许多十进制小数无法精确存储:
print(0.1) # 0.1,显示时四舍五入
print(repr(0.1)) # '0.1000000000000000055511151231257827021181583404541015625'
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
这不是 Python 的 bug,而是二进制浮点的固有特性。C、Java、JavaScript 等语言同样存在此问题。
正确比较浮点数:
# 方法1:使用 round 限定精度
print(round(0.1 + 0.2, 10) == 0.3) # True
# 方法2:使用 math.isclose
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
精度累积:连续运算会放大误差:
# 累加 0.1 十次
s = 0.0
for _ in range(10):
s += 0.1
print(s) # 0.9999999999999999
print(s == 1.0) # False
特殊值:inf 和 nan
浮点数有两个特殊值,由 float() 或运算产生:
inf(无穷大):
print(1e308) # 1e+308
print(1e309) # inf,溢出为正无穷
print(float('inf')) # inf
print(1.0 / 0.0) # ZeroDivisionError!不是 inf
注意:整数除零报错,但浮点运算中某些情况产生 inf:
import math
print(math.exp(1000)) # inf
print(1e308 * 1e10) # inf
nan(非数字):
nan = float('nan')
print(nan) # nan
print(nan == nan) # False,nan 与任何值都不相等,包括自身
print(math.isnan(nan)) # True,判断 nan 的正确方式
nan 会"传染"运算结果:
print(nan + 1) # nan
print(nan * 0) # nan,不是 0
Decimal 替代方案
对于需要精确十进制表示的场景(如货币计算),应使用 decimal 模块:
from decimal import Decimal, getcontext
# 用字符串构造,避免先经过不精确的 float
price = Decimal("0.1")
print(price + Decimal("0.2")) # 0.3,精确
# 设置全局精度
getcontext().prec = 6
print(Decimal("1") / Decimal("7")) # 0.142857
Decimal 从 float 构造会继承其不精确性,从 int 或字符串构造才是精确的:
print(Decimal(0.1)) # 不精确,继承 float 的二进制误差
print(Decimal("0.1")) # 精确
边界情况
整数与浮点混合运算:结果提升为 float,大整数可能丢失精度:
print(2 ** 53) # 9007199254740992
print(float(2 ** 53)) # 9.007199254740992e+15
print(float(2 ** 53 + 1) == float(2 ** 53)) # True,精度丢失
float 的范围:
print(1.8e308) # inf,超出最大值
print(5e-324 == 0.0) # False,最小正正规数
print(1e-324 == 0.0) # True,下溢为零
格式化输出:控制显示精度避免误导:
print(f"{0.1 + 0.2:.2f}") # 0.30
print(f"{math.pi:.6f}") # 3.141593
浮点数是强大的工具,但使用时必须清楚其精度限制。核心原则:需要精确十进制结果时,用 Decimal;需要精确整数时,用 int;float 适合科学计算和近似值。