← 返回题目列表

Python 中 int、float、Decimal 有什么区别?

高频 中等 第 12 / 21 题 更新于 2026/07/25
PythonintfloatDecimal精度

简化版

int 表示整数,Python 里的整数支持任意精度;float 是双精度浮点数,适合科学计算但存在二进制精度误差;Decimal 是十进制小数,适合金额、财务等需要可控精度的场景。

详细版

例子:

print(0.1 + 0.2)  # 0.30000000000000004

这不是 Python 算错了,而是二进制浮点数无法精确表示很多十进制小数。

金额场景更推荐:

from decimal import Decimal

price = Decimal("0.1")
tax = Decimal("0.2")
print(price + tax)  # 0.3

区别:

类型特点适合场景
int任意精度整数计数、ID、位运算、精确整数
float二进制浮点数,速度快但有误差科学计算、近似计算
Decimal十进制精确计算,可控制舍入金额、财务、精度敏感

注意:创建 Decimal 时尽量从字符串创建,不要从 float 创建:

Decimal("0.1")   # 推荐
Decimal(0.1)     # 会带入 float 误差

完整版教学

一、先按“精确性”和“表示方式”分

intfloatDecimal 的区别不是“谁高级”,而是解决不同问题。int 表示精确整数,Python 会自动扩展位数;float 表示二进制浮点近似值,速度快、生态广,但不能精确表示很多十进制小数;Decimal 表示十进制小数,能控制精度和舍入,更适合金额和财务规则。

类型表示方式精确性典型场景
int任意精度整数整数精确计数、ID、位运算
floatIEEE 754 双精度二进制浮点近似科学计算、机器学习、指标
Decimal十进制小数可控十进制精度金额、税率、财务结算

面试时不要简单说“float 不精确,Decimal 精确”就结束。更准确是:float 对二进制可表示的数可以精确,对很多十进制小数只能近似;Decimal 能按十进制语义表示和舍入,但仍受上下文精度和业务量化规则约束。

二、Python int 为什么说是任意精度

在很多语言里,整数有固定范围,例如 32 位或 64 位。Python 的 int 会根据数值大小自动扩展精度,只受可用内存限制。

n = 10 ** 100
print(n)

这对开发很友好,不容易整数溢出。但代价是超大整数运算比固定机器整数更重。

常见用途:

  • 计数;
  • 下标;
  • ID;
  • 时间戳;
  • 位运算;
  • 精确整数计算。

如果用 64 位有符号整数,最大值约是 9.22e18;而 Python 的 10 ** 100 远远超过这个范围仍能正确表示。代价是大整数越大,占用的内存越多,运算也越慢。比如处理密码学大数、超大阶乘时,Python 写起来简单,但不代表没有性能成本。

三、float 的误差从哪里来

float 通常使用 IEEE 754 双精度二进制浮点数。问题在于,很多十进制小数无法用有限二进制精确表示。

就像十进制无法精确表示 1/3

0.333333...

二进制也无法精确表示很多十进制小数,例如 0.1

所以:

0.1 + 0.2 == 0.3

结果是:

False

比较 float 时应该使用容差:

import math

math.isclose(0.1 + 0.2, 0.3)

可以用公式理解浮点比较:

不要直接判断 a == b
应该判断 abs(a - b) <= 可接受误差

math.isclose 默认会结合相对误差和绝对误差,比手写简单容差更稳。面试里重点不是背 IEEE 754 的全部细节,而是能说出二进制表示导致十进制小数近似、比较要用容差、金额不要用 float 做核心计算。

易错点:0.1 + 0.2 的显示结果不是 Python 算错,而是二进制浮点近似值转换回十进制展示时暴露了误差。

四、Decimal 为什么适合金额

Decimal 按十进制语义处理小数,并且可以配置精度和舍入规则。

from decimal import Decimal, getcontext

getcontext().prec = 10
amount = Decimal("19.99")
count = Decimal("3")
print(amount * count)

金额计算关心的是十进制下的精确表达和舍入规则,所以不应该用 float 承担核心计算。

尤其不要这样:

Decimal(0.1)

因为 0.1 在传给 Decimal 前已经是带误差的 float。

正确创建方式通常是字符串或整数:

from decimal import Decimal, ROUND_HALF_UP

amount = Decimal("19.995")
print(amount.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))  # 20.00

quantize 很重要,因为财务金额不仅关心“算得精确”,还关心保留几位小数和如何舍入。不同业务可能要求四舍五入、银行家舍入、向上取整等规则,Decimal 给你的是可控能力,不是自动替你决定业务规则。

五、什么时候可以放心用 float

float 并不是坏东西,它适合大量近似数值计算:

  • 科学计算;
  • 机器学习;
  • 图形计算;
  • 统计估算;
  • 对微小误差不敏感的指标。

这些场景通常更关心性能和数值方法,而不是每一位十进制小数完全符合财务规则。

机器学习和科学计算大量使用 float,是因为它速度快、硬件支持好、内存占用可控。比如 100 万个浮点特征用双精度大约 8MB 原始数值空间;如果每个都用 Decimal,对象开销和运算成本会高很多。选择类型要看误差是否可接受,而不是一看到小数就用 Decimal。

六、类型转换和混用边界

不要随意混用 floatDecimalDecimal("0.1") 表示精确十进制 0.1;Decimal(0.1) 会把 float 已经存在的二进制误差带进来。Python 也不允许 Decimal 和 float 直接做某些算术混合,这是为了逼你明确语义。

from decimal import Decimal

print(Decimal("0.1") + Decimal("0.2"))  # 0.3
print(Decimal(0.1))  # 0.100000000000000005551...

整数和 Decimal 混用通常更安全,因为整数本身精确。但只要进入 float,十进制精确语义就可能丢失。涉及金额的接口入参最好用字符串、整数分单位(如分)或 Decimal,而不是 float。

七、常见误区与追问

  • 误区:Python 的 int 会像 Java int 一样固定 32 位溢出。 Python int 会自动扩展精度,不固定 32 位,但超大整数有内存和性能成本。
  • 误区:float 是错误类型,不能用。 float 适合近似数值计算,问题是不要把它用于必须十进制精确的金额结算。
  • 误区:Decimal(0.1) 就能消除 0.1 的误差。 传入 Decimal 前 0.1 已经是 float 近似值,应该用 Decimal("0.1")
  • 追问:为什么 0.1 + 0.2 != 0.3 很多十进制小数无法用有限二进制浮点精确表示,计算结果只是近似。
  • 追问:float 比较应该怎么做?math.isclose 或业务容差,而不是直接 == 比较计算结果。
  • 追问:金额为什么还要考虑舍入规则? Decimal 能精确表示十进制数,但保留几位、如何进位是业务规则,需要 quantize 等方式明确。

八、加强记忆

把这题记成“三种数字三种承诺”:int 承诺整数精确且自动扩展,float 承诺高效近似和硬件友好,Decimal 承诺十进制语义和可控舍入。计数、ID、位运算用 int;科学计算、机器学习、指标估算用 float;金额、税率、财务结算用 Decimal 或整数分单位。回答时一定带上 0.1 + 0.2math.iscloseDecimal("0.1") 这三个关键点。