page contents

Python 整数能一直变大,小数却算不准?

Python 区分 int、float 和 complex,分别表示整数、浮点数和复数。它们能表示什么、是否精确,取决于各自的存储方式。

attachments-2026-09-kgcz8X8K6aa2096c49b3a.png一个很大的整数加上 1,结果竟然没有变化。这不是加法失效,而是数字类型已经无法精确表示这个结果。

Python 区分 int、float 和 complex,分别表示整数、浮点数和复数。它们能表示什么、是否精确,取决于各自的存储方式。

但这不代表 Python 的所有数字都能无限精确。整数能精确保存大数,浮点数仍然会遇到熟悉的 0.1 + 0.2 问题。

三种数字类型

先看写法。同样表达数值,是否带小数点、指数或虚数后缀,会影响 Python 创建的类型。

count = 42
price = 42.0
distance = 1e3
signal = 3 + 4j

print(type(count))     # <class 'int'>
print(type(price))     # <class 'float'>
print(distance)        # 1000.0:科学计数法写法创建 float
print(type(signal))    # <class 'complex'>

int 整数:例如 0、42、-7,适合计数、索引和整数运算。

float 浮点数:例如 3.14、-0.5、1e3,适合允许近似误差的数值计算。

complex 复数:例如 3 + 4j、2j,由实部和虚部组成,常见于科学计算。

42 和 42.0 的数值相等,类型却不同。不要只看输出有没有小数,就判断数字是什么类型。

print(42 == 42.0)                # True:数值相等
print(type(42) is type(42.0))     # False:类型不同

前面提及过,bool 是 int 的子类,但表达的是真假。这里聚焦三种内置数值类型,不把布尔值当作普通业务数量使用。

1. int:整数没有固定位宽。

Python 的 int 支持任意精度。它不会因为超过 32 位或 64 位整数范围,就自动溢出或变成浮点数。

large = 2 ** 100

print(large)       # 1267650600228229401496703205376
print(large + 1)   # 1267650600228229401496703205377
print(type(large)) # <class 'int'>

“无限大整数”是一种简化说法,更准确的理解是:没有固定的位数上限,但仍受可用内存和计算资源限制。

大整数依然精确:整数加、减、乘等运算可以保持整数精度。

数字越大,成本越高:保存和计算大整数需要更多内存与时间。

任意精度不等于无穷大:int 保存的是有限整数,不能用来表示数学上的无穷大。

尤其要注意:整数本身精确,不代表把它转成其他类型后也能保留全部信息。

original = 2 ** 53 + 1
converted = float(original)

print(original)        # 9007199254740993
print(converted)       # 9007199254740992.0:转换时已经丢失精度
print(int(converted))  # 9007199254740992:转回 int 也无法恢复

如果大整数运算需要保持精确,应避免中途转换为 float。过大的整数转浮点数,还可能抛出 OverflowError。

2. float:浮点并非精确小数。

Python 的 float 在常见平台上采用 IEEE 754 双精度二进制浮点表示,能保存的有效数字位数有限。

关键在“二进制”:有些十进制小数无法用有限位二进制精确表示,保存时只能取近似值。

# 误区示例:以为小数加法一定能得到精确的十进制结果
print(0.1 + 0.2)         # 0.30000000000000004
print(0.1 + 0.2 == 0.3)  # False

# 并不是所有小数都有这个问题
print(0.5 + 0.25 == 0.75)  # True:这些值能用二进制精确表示

精度限制也会影响很大的整数值。超过一定范围后,相邻两个整数可能被保存成同一个浮点数。

large = float(2 ** 53)

print(large + 1 == large)  # True:加 1 后无法表示新的相邻整数
print(large + 2 == large)  # False:这个位置仍能区分相差 2 的值

显示位数不等于存储精度:f"{value:.2f}" 生成两位小数的字符串,不会改变原来的浮点值。

四舍五入不等于精确存储:round() 不能把二进制浮点数变成精确十进制类型。

近似计算按容差比较:容差应来自业务对误差的要求,不要随意固定一个值适用于所有计算。

固定小数位金额可用整数最小单位:例如用“分”保存金额;需要十进制规则时,可进一步学习标准库 Decimal。

value = 0.1 + 0.2
display = f"{value:.2f}"

print(display)        # 0.30
print(type(display))  # <class 'str'>:这是展示文本
print(value)          # 0.30000000000000004:原值没有改变

3. complex:复数由实部和虚部组成。

Python 内置复数类型,用 j 或 J 表示虚数单位。3 + 4j 是一个复数,"3 + 4j" 才是字符串。

z = 3 + 4j

print(type(z))    # <class 'complex'>
print(z.real)     # 3.0:实部
print(z.imag)     # 4.0:虚部
print(abs(z))     # 5.0:模,即到原点的距离
print(1j * 1j)   # (-1+0j):虚数单位的平方等于 -1

只写 j 会被当成变量名。表示虚数单位时,要写 1j;通过变量组合复数时,可以使用 complex(real, imag)。

real = 3
imag = 4
z = complex(real, imag)

print(z)            # (3+4j)
print(z + 2)        # (5+4j)
print(z * 2)        # (6+8j)
print(z == 3 + 4j)  # True

# 错误示例:复数不支持大小排序
# print(z > 2)  # TypeError

支持数值运算:可以进行加、减、乘、除等运算。

不支持大小比较:不能直接使用 <、>,但可以比较是否相等。

不支持地板除法和取余:不能直接使用 //、%。

不是任意精度复数:实部和虚部使用浮点数表示,同样存在精度限制。

了解三种类型后,还要注意混合运算可能改变结果类型。对内置的 int、float、complex 进行加、减、乘等运算时,结果通常向能容纳参与类型的方向转换。

print(2 + 3)         # 5:int
print(2 + 3.0)       # 5.0:float
print(2 + 3j)        # (2+3j):complex
print(2.0 + 3j)      # (2+3j):complex

这不意味着原变量被修改,也不保证转换过程无精度损失。特别是大整数参与浮点运算时,要留意前面的精度边界。

除法还要单独记忆:两个整数使用 /,即使能整除,结果也是 float;两个整数使用 //,结果才是 int。

print(6 / 3)         # 2.0
print(type(6 / 3))   # <class 'float'>
print(6 // 3)        # 2
print(6 // 3.0)      # 2.0:有浮点操作数,结果也是浮点数

不要把“/ 总是得到浮点数”扩展到所有数值类型。复数参与普通除法时,结果是复数。

print((4 + 2j) / 2)  # (2+1j)

与 JS 比精度

Python 的 int 能精确处理大整数,JS 的普通数字 Number 则有安全整数范围。

但小数计算上,Python 的 float 和 JS 的 Number 都有二进制浮点误差。

JS 的 Number 安全整数范围是 -(2 ** 53 - 1) 到 2 ** 53 - 1。超过范围不代表每个整数都不精确,而是不能保证每个相邻整数都可区分。

大整数加 1:2 ** 53 + 1 在 Python 中精确得到 9007199254740993,在 JS 中得到 9007199254740992。

小数相加:0.1 + 0.2 在两者中都得到 0.30000000000000004。

精确保存大整数:Python 直接使用 int;JS 使用 BigInt,如 9007199254740993n。

大整数转浮点表示:Python 转成 float、JS 转成 Number 后,都可能丢失精度。

JS 的 BigInt 也能精确表示大整数,但不能表示小数。若先用 Number 保存大整数,再转 BigInt,已经丢失的精度同样不会恢复。

Python 的优势在于 int 直接支持任意精度整数,不代表 float 比 JS 的 Number 更精确。

实战金额计算

假设商品价格固定到“分”,数量必须是正整数。可以让价格和总金额始终使用 int,最后只在展示时拼接小数点。

def calculate_total(price_fen, quantity):
    # 精确检查 int,同时排除 bool
    if type(price_fen) is not int or type(quantity) is not int:
        raise TypeError("单价(分)和数量必须是整数")
    if price_fen < 0 or quantity <= 0:
        raise ValueError("单价不能为负,数量必须大于零")

    return price_fen * quantity


price_fen = 1990
quantity = 3
total_fen = calculate_total(price_fen, quantity)
display = f"{total_fen // 100}.{total_fen % 100:02d}"

print(total_fen)      # 5970
print(display)        # 59.70
print(type(display))  # <class 'str'>

# calculate_total(19.9, 3)  # TypeError:这里要求输入整数分
# calculate_total(1990, True)  # TypeError:不接受布尔值作为数量

这段代码适用于输入已经是整数分的场景。不要先把小数金额转成 float,再指望 int(amount * 100) 自动消除误差。

涉及折扣、税率或更多小数位时,需要另外明确精度和舍入规则,不能直接套用上面的整数乘法。

数字使用准则

保存整数、计数或精确大整数时,优先使用 int,无需额外声明大整数类型。

float 适合近似计算,不适合承诺任意小数都精确;格式化只改变展示。

complex 使用 j 表示虚部,支持复数运算,但不支持直接比较大小。

大整数转成 float 或参与浮点运算后,可能丢失精度,转回整数无法补救。

选择类型时,先明确是否需要整数精确性、是否接受误差,再决定如何计算和展示。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 

  • 发表于 2026-09-10 09:35
  • 阅读 ( 37 )
  • 分类:Python开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2420 篇文章

作家榜 »

  1. Pack 2420 文章
  2. 轩辕小不懂 2403 文章
  3. 小柒 2228 文章
  4. Nen 576 文章
  5. 王昭君 216 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章