我用 Python 的 float 累加金额做对账,几万笔加下来总额和数据库就是差了几分钱,我对着浮点数精度排查了大半天的复盘

写了个对账脚本,把几万笔交易金额用 Python float 累加和数据库总额核对,逻辑简单到不能再简单,结果死活对不上——我算的总额和数据库总是差那么几分钱。反复检查数据没漏没重、加法没写错,可几万笔加完就是差 0.03 这种诡异小数。一度怀疑数据库、怀疑数据精度,最后敲了行 0.1 + 0.2 看到输出 0.30000000000000004 才恍然大悟:问题出在 float 本身,它根本存不准小数。根因是 float 用二进制存数,0.1(=1/10)在二进制是无限循环小数、只能存近似值;单次误差在第17位看不见,但几万笔累加误差不断累积放大成"差几分钱";而且这是所有 IEEE754 语言通病不是 Python bug。这篇从 float 为何存不准小数、用 Decimal(必须字符串构造)或整数存分/float比较用isclose容差的正解、float 能用与绝不能用的边界(容不容忍误差,别矫枉过正全用Decimal它慢几十倍)、三种数值表示对比、浮点其他坑(精确比较/大数吃小数/round银行家舍入/NaN)、决策图与铁律,到附上一段累加100万次0.1亲眼看误差累积的实验。核心领悟:计算机里的一切都是对现实的有限近似而非现实本身(数字近似数学、字符近似文本、时间近似时间),把抽象当现实就会在它近似而非精确的缝隙里栽跟头;越基础越想当然的概念越要吃透其边界和代价。

我用 Python 的 float 累加金额做对账,几万笔加下来总额和数据库就是差了几分钱,我对着浮点数精度排查了大半天的复盘

那是我写的一个对账脚本:把几万笔交易的金额用 Python 累加起来,和数据库里记录的总额做核对。逻辑简单到不能再简单,可结果就是死活对不上——我算出来的总额,和数据库的总额,总是差那么几分钱。我反复检查:数据没漏、没重、每一笔都对得上,加法也没写错。可几万笔加完,总额就是差了 0.03 这种诡异的小数。我一度怀疑是数据库的问题、是数据精度的问题。排查了大半天,最后用 Python 敲了一行 0.1 + 0.2,看到输出是 0.30000000000000004 时,我才恍然大悟:问题出在浮点数(float)本身,它根本就存不准小数。这篇就把这场"float 算钱算不准"的事故,从头复盘一遍。

故障现场:0.1 + 0.2 居然不等于 0.3

先看现场。一行最简单的加法,就暴露了 float 的真面目:

# 我的对账代码: 用 float 累加金额
total = 0.0
for txn in transactions:        # 几万笔交易
    total += txn.amount         # txn.amount 是 float, 如 19.99, 0.1, ...
# 最后 total 和数据库总额 差几分钱

# 一行代码揭示真相:
>>> 0.1 + 0.2
0.30000000000000004             # ← 不是 0.3 !
>>> 0.1 + 0.2 == 0.3
False                           # ← 居然是 False !
>>> 0.3 - 0.2
0.09999999999999998            # ← 也不是 0.1 !

# 为什么? float 是"二进制浮点数", 它存不准很多十进制小数:
>>> from decimal import Decimal
>>> Decimal(0.1)               # 看看 0.1 在 float 里"真实"存的是什么:
Decimal('0.1000000000000000055511151231257827021181583404541015625')
#   ↑ 0.1 这个十进制小数, 在二进制浮点里, 根本无法精确表示!
#     存进去的是一个"无限接近 0.1、但不等于 0.1"的近似值。

# 现象拼图:
#   - 计算机用二进制存数。1/2, 1/4 这种能精确表示, 但 0.1(=1/10)
#     在二进制里是【无限循环小数】, 就像 1/3 在十进制里是 0.333...一样。
#   - float(双精度)只有有限位数, 只能存 0.1 的一个【近似值】(略有误差)。
#   - 单次运算误差极小(小数点后十几位), 你平时看不出来。
#   - 但: 几万笔金额累加, 这些微小的误差会【不断累积、放大】,
#     最终汇成了"差几分钱"的可见误差 → 对账对不上!
#   - ★ 根因: float 天生存不准十进制小数, 它不适合用来做"需要精确"的
#     金额/货币计算。我用错了数据类型。

看到 0.1 + 0.2 == 0.3 返回 False 时,我才明白对账对不上的根子在哪。问题出在 float(二进制浮点数)本身——它存不准很多十进制小数原因是:计算机用二进制存数,1/21/4 能精确表示,但 0.1(=1/10)在二进制里是无限循环小数(就像 1/3 在十进制里是 0.333…),而 float 只有有限位数,只能存 0.1 的一个近似值(略有误差)单次运算的误差极小(小数点后十几位),平时看不出来;但几万笔金额累加,这些微小误差会不断累积、放大,最终汇成"差几分钱"的可见误差,导致对账对不上根因很清楚:float 天生存不准十进制小数,它不适合用来做"需要精确"的金额/货币计算——我从一开始就用错了数据类型

第一件事:搞懂 float 为什么存不准小数

要解决它,得先理解浮点数的本质,以及它"精度问题"是怎么来的。

浮点数(float)精度问题的本质

# 一、float 是怎么存数的? —— 二进制科学计数法
#   - float(IEEE 754 双精度)用二进制存: 符号位 + 指数 + 尾数。
#   - 它能精确表示的, 是"能写成 二进制有限小数"的数:
#     1/2=0.1₂, 1/4=0.01₂, 0.75=0.11₂ ... 这些都精确。
#   - 但 0.1(十进制)= 1/10, 在二进制里是 0.0001100110011...(无限循环)!
#     就像 1/3 在十进制是 0.333... 写不尽一样。

# 二、为什么会有误差?
#   - float 尾数位数有限(双精度约15-17位十进制有效数字)。
#   - 存 0.1 这种"二进制无限循环"的数, 只能截断成有限位 → 存的是近似值。
#   - 这个近似值 ≈ 0.1 但 ≠ 0.1, 误差在小数点后约17位。

# 三、误差怎么"放大"成可见问题?
#   - 单次: 0.1 + 0.2 = 0.30000000000000004, 误差在第17位。
#   - 累加: 几万次运算, 误差不断累积; 或大数+小数时小数的精度被"吃掉"。
#   - 比较: 0.1+0.2 == 0.3 为 False(两边的近似误差不同)。
#   - 这些在"金额、计数、需要精确相等判断"的场景, 就是致命的。

# 四、关键认知: 这不是 Python 的 bug, 是所有用 IEEE754 的语言通病!
#   - Java、C、JS、Go... 的 float/double 都有这个问题(JS 全是 float 更明显)。
#   - 它是"二进制表示十进制小数"的固有局限, 不是哪个语言写错了。

# 核心: float用二进制存数, 0.1等十进制小数在二进制是无限循环、只能存近似值;
#   误差在累加/比较时放大; 这是所有IEEE754语言的通病, 金额等精确场景不能用float。

想透浮点数的本质,这个"诡异"的现象就一点都不诡异了。一、float 怎么存数?——用二进制科学计数法,能精确表示的是"能写成二进制有限小数"的数(1/2、1/4、0.75);但 0.1(=1/10)在二进制里是无限循环小数,就像 1/3 在十进制写不尽一样二、为什么有误差?——float 尾数位数有限,存 0.1 这种二进制无限循环的数只能截断成有限位,存的是近似值(≈0.1 但 ≠0.1)三、误差怎么放大?——单次误差在第 17 位看不出来,但几万次累加误差不断累积、或大数+小数时小数精度被吃掉、或精确相等比较时为 False;在金额/计数/精确判断场景就是致命的四、关键认知:这不是 Python 的 bug,是所有用 IEEE 754 的语言通病——Java、C、JS、Go 的 float/double 都有这个问题,它是"二进制表示十进制小数"的固有局限

第二件事:正解——金额用 Decimal 或整数(分),别用 float

搞懂了原理,正解就清晰了:精确的金额计算用 Decimal(十进制定点)或"用整数存分";比较浮点数用容差;别对 float 做精确相等判断

from decimal import Decimal, ROUND_HALF_UP

# ====== 正解一(推荐): 用 Decimal 做金额计算 ======
# Decimal 是"十进制"数, 精确表示十进制小数, 没有 float 的二进制误差。
a = Decimal("0.1")          # ★ 关键: 用【字符串】构造, 别用 Decimal(0.1)!
b = Decimal("0.2")
print(a + b)                # Decimal('0.3')  ← 精确!
print(a + b == Decimal("0.3"))   # True  ← 精确相等!

# 对账累加:
total = Decimal("0")
for txn in transactions:
    total += Decimal(str(txn.amount))   # 从源头就用 Decimal(或存字符串)
# → total 精确, 和数据库对得上!

# 注意: Decimal(0.1) 是错的! 它会把"已经不准的 float 0.1"转进来:
print(Decimal(0.1))         # Decimal('0.1000000000000000055511...') ← 还是脏的!
print(Decimal("0.1"))       # Decimal('0.1')  ← 干净! 必须用字符串构造。

# ====== 正解二: 用"整数(最小单位)"存金额 —— 即"用分代替元"======
# 把金额统一用"分"(整数)存和算, 彻底避开小数:
price_cents = 1999          # 19.99元 存成 1999分
total_cents = 0
for txn in transactions:
    total_cents += txn.amount_cents   # 整数加法, 绝对精确
# 显示时再转成元: total_cents / 100
# → 很多金融系统就是这么做的: 底层全用整数(分/厘), 杜绝浮点。

# ====== 正解三: 必须用 float 时, 比较用"容差", 别用 == ======
import math
x = 0.1 + 0.2
print(x == 0.3)                          # False (别这么比!)
print(math.isclose(x, 0.3))              # True  ✓ 用 isclose 带容差比较
print(abs(x - 0.3) < 1e-9)               # True  ✓ 或手动设容差 epsilon

# ====== 正解四: Decimal 的舍入要显式指定(金额舍入很关键)======
amount = Decimal("19.995")
# 保留2位小数, 四舍五入(银行家舍入 ROUND_HALF_EVEN 也常用)
print(amount.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))  # 20.00
# → 别用 round()(它对 float 也有精度坑); 用 Decimal.quantize 明确舍入规则。

# ====== 正解五: 各语言的对应方案 ======
# Java: BigDecimal(同样要用 new BigDecimal("0.1") 字符串构造!)
# JS:   用整数(分)、或 decimal.js / big.js 库
# Go:   shopspring/decimal 库, 或整数

# 核心: 金额精确计算用 Decimal(必须用字符串构造!)或整数存分; float比较用isclose容差;
#   Decimal舍入用quantize显式指定; 各语言都有对应方案(Java BigDecimal等)。

修复的核心,是"金额这种需要精确的计算,换用能精确表示十进制的类型,别用 float"正解一(推荐):用 Decimal——Decimal 是十进制数,精确表示十进制小数、没有二进制误差(Decimal("0.1") + Decimal("0.2") == Decimal("0.3") 为 True);关键是必须用字符串构造 Decimal("0.1"),绝不能用 Decimal(0.1)(那会把已经不准的 float 0.1 转进来,还是脏的)正解二:用整数(最小单位)存金额——把金额统一用"分"(整数)存和算,彻底避开小数(很多金融系统就这么做)。正解三:必须用 float 时,比较用容差——用 math.iscloseabs(x-y) < 1e-9,别用 ==正解四:Decimal 舍入用 quantize 显式指定(别用 round(),它对 float 也有坑)。正解五:各语言都有对应方案(Java BigDecimal 同样要字符串构造、JS 用整数或 decimal.js、Go 用 decimal 库)。归根结底:金额精确计算用 Decimal(必须字符串构造)或整数存分;float 比较用 isclose 容差;Decimal 舍入用 quantize;各语言都有对应方案。

第三件事:什么时候能用 float、什么时候绝不能

排查后我把"float 能不能用"的边界彻底搞清了,免得从一个极端走向另一个极端。

float 的适用边界

# ✗ 绝不能用 float 的场景(需要"精确"):
#   1. 金额、货币、财务计算(本文)—— 差一分钱都是事故。
#   2. 需要精确相等判断的(== 比较)。
#   3. 大量累加/累乘(误差会累积放大)。
#   4. 需要精确十进制表示的(如精确到分的价格)。
#   → 这些用 Decimal 或 整数。

# ✓ 可以用 float 的场景(容忍微小误差):
#   1. 科学计算、工程计算、统计(本就有测量误差, 浮点误差可忽略)。
#   2. 图形、游戏、物理模拟(坐标差 1e-15 无所谓)。
#   3. 机器学习(权重、概率, 本就是近似)。
#   4. 比例、百分比的中间计算(最后结果取整/容差处理)。
#   → 这些 float 又快又够用(Decimal 慢得多)。

# 关键判断: "这个计算, 容忍微小的误差吗?"
#   - 容忍(科学/图形/ML)→ float, 快。
#   - 不容忍(钱/精确比较)→ Decimal/整数, 准。

# 一个常见误区(别矫枉过正):
#   - 不是"float 一无是处、什么都用 Decimal"。
#   - Decimal 精确但【慢很多】(约几十倍), 内存也大。
#   - 科学计算、ML 用 Decimal 是灾难(慢且没必要)。
#   - 正确: 按"是否需要精确"选, 该 float 用 float, 该 Decimal 用 Decimal。

# 核心: 金额/精确比较/大量累加 绝不用float(用Decimal/整数); 科学/图形/ML 可用float
#   (快且容忍误差); 判断标准是"容不容忍微小误差", 别矫枉过正全用Decimal(它慢)。

排查后我厘清了"float 能不能用"的边界,避免从一个极端走向另一个极端。绝不能用 float 的场景(需要精确):金额/货币/财务(差一分都是事故)、需要精确相等判断、大量累加累乘(误差累积)、需要精确十进制表示——这些用 Decimal 或整数。可以用 float 的场景(容忍微小误差):科学/工程/统计计算(本就有测量误差)、图形/游戏/物理模拟、机器学习(权重概率本就近似)、比例百分比的中间计算——这些 float 又快又够用。关键判断就一句:"这个计算,容忍微小的误差吗?"——容忍就用 float(快),不容忍就用 Decimal/整数(准)而一个常见误区是别矫枉过正:不是"float 一无是处、什么都用 Decimal"——Decimal 精确但慢很多(约几十倍)、内存也大,科学计算/ML 用 Decimal 是灾难;正确做法是按"是否需要精确"选下面这张图,是这次 float 算钱对不上的成因与解法:

第四件事:float vs Decimal vs 整数(分)对比速查

这次踩坑后,我把三种数值表示方式整理成一张表,按场景对照着选。

方式 精确度 性能 适用
float 有二进制误差 科学/图形/ML,容忍误差
Decimal 精确(十进制) 慢(约几十倍) 金额/财务,需精确
整数(分/厘) 精确 最快 金额,性能敏感

这张表,把三种方式的取舍摆清了。核心是:容忍误差、要性能用 float;要精确的金额用 Decimal(可读性好)或整数存分(最快)它给我的启发是:"数字"在计算机里,从来不是一个理所当然、唯一的概念,而是有多种表示方式,每种都在"精确度、性能、范围、可读性"之间做了不同的权衡我之前犯错,正是因为把 float 当成了"数字"的默认、唯一选择——看到一个带小数的金额,想都没想就用了 float,完全没意识到"用什么类型来表示这个数"本身就是一个需要根据场景认真决策的问题。这让我领悟到:选择正确的"数据类型/表示方式",是写出正确程序的第一步,也是最容易被忽略的一步;很多 bug,不是逻辑写错了,而是"用错了承载数据的类型"——用 float 装钱、用 int 装可能溢出的大数、用普通字符串装需要精确比较的东西……所以,每当我要表示一个重要的数据,我都会多想一步:"这个数据的本质要求是什么(精确?范围?性能?),什么类型最匹配这个要求?"——选对了类型,等于在地基上就避开了一大类问题。

第五件事:浮点数的其他常见坑

金额只是浮点数最典型的坑,它还有几个常见陷阱,我一并梳理了。

现象 对策
精确相等比较 0.1+0.2 == 0.3 为 False 用 math.isclose / 容差
累加误差放大 大量累加后偏差明显(本文) Decimal / 整数 / math.fsum
大数吃小数 1e16 + 1 还是 1e16 注意数量级差距,排序后加
round 的银行家舍入 round(2.5)=2 不是 3 明确舍入规则,金额用 Decimal.quantize
float 转字符串显示 显示出一长串小数 格式化指定位数 f"{x:.2f}"
NaN/Inf 0.0/0.0=nan, nan != nan 用 math.isnan 判断

这张表,把浮点数的"坑系列"列全了。除了金额累加,还有:精确相等比较为 False、大数吃小数(1e16 + 1 还是 1e16)、round 的银行家舍入(round(2.5)=2)、显示出一长串小数、NaN 的诡异行为(nan != nan)它给我的最大启发是:浮点数,是一个我们"每天都在用、却很少真正理解"的东西;它表面上就是"带小数的数字",朴素得不能再朴素,背后却藏着一整套由"二进制表示有限"带来的、反直觉的行为这其实是很多"基础概念"的共性:越是"基础、看起来简单、人人都在用"的东西(浮点数、字符编码、时间日期、整数溢出),越容易被我们"想当然",也越容易在不经意间埋下坑;因为我们对它们太熟悉了,熟悉到从不怀疑自己是否真的理解它们这让我对"基础"多了一份敬畏:真正吃透那些"简单到不值得深究"的基础概念(它的原理、它的边界、它反直觉的地方),往往比学一个花哨的新框架,更能避开那些最隐蔽、也最普遍的 bug地基上的裂缝,远比顶楼的裂缝更危险。

第六件事:遇到一个"数"时,我现在的类型决策习惯

现在每当我要表示或计算一个数,我都会先想清楚"它要不要精确":

这张图的精髓,是"用一个数前,先问'它要不要精确'"第一问 "这个数需要精确吗":不需要(科学/图形/ML/统计)就用 float(快且够用);需要精确(钱/计数/精确比较)再细分。需要精确时:金额且性能敏感用整数存分/厘、金额一般用 Decimal(字符串构造)、其他精确数用 Decimal 或整数而用 float 时,要比较就用 math.isclose 容差、别用 ==最后显示时再转换 + 格式化指定位数这套习惯,让我处理数字时,从"带小数就用 float"变成了"先想它要不要精确"——核心始终是:float 存不准十进制小数,需要精确的场景(尤其金额)必须用 Decimal 或整数。

我立下的几条规矩

这场"float 算钱对不上"的事故,换来了我写代码时,刻进骨子里的几条铁律:

  1. 金额绝不用 float。float 存不准十进制小数,累加误差会放大成对账对不上。
  2. 金额用 Decimal 或整数(分)。Decimal 精确可读,整数存分最快,金融底层常用整数。
  3. Decimal 必须用字符串构造。Decimal("0.1") 才干净,Decimal(0.1) 会把脏 float 带进来。
  4. float 比较用容差,别用 ==。math.isclose 或 abs(a-b)
  5. 舍入用 Decimal.quantize 明确规则。别用 round(它对 float 有坑、还有银行家舍入)。
  6. 按"要不要精确"选类型,别矫枉过正。科学/ML 仍用 float,Decimal 慢几十倍。
  7. 这是所有 IEEE754 语言通病。Java BigDecimal、JS 整数、Go decimal,都一样。

附:一段亲手验证 float 之坑与 Decimal 之解的实验

口说无凭。下面这段代码,让你亲眼看见 float 累加的误差、以及 Decimal/整数的精确,跑一遍胜过看十遍:

from decimal import Decimal

# ====== 实验1: 经典的 0.1 + 0.2 ======
print("float:  0.1 + 0.2 =", 0.1 + 0.2)              # 0.30000000000000004
print("float:  == 0.3 ?  ", 0.1 + 0.2 == 0.3)        # False
print("Decimal:", Decimal("0.1") + Decimal("0.2"))   # 0.3
print("Decimal == ?", Decimal("0.1") + Decimal("0.2") == Decimal("0.3"))  # True
print()

# ====== 实验2: 累加误差(模拟对账)======
# 把 0.1 累加 100 万次, 理论上应该是 100000.0
n = 1_000_000

# float 版: 误差累积
total_float = 0.0
for _ in range(n):
    total_float += 0.1
print(f"float 累加100万次0.1  = {total_float}")        # 不是 100000.0! 有误差
print(f"  与理论值100000差 = {total_float - 100000}")   # 一个非零的小数!

# Decimal 版: 精确
total_dec = Decimal("0")
step = Decimal("0.1")
for _ in range(n):
    total_dec += step
print(f"Decimal 累加100万次 = {total_dec}")            # 100000.0 精确!

# 整数(分)版: 精确且最快
total_cents = 0
for _ in range(n):
    total_cents += 10                                  # 0.1元 = 10分
print(f"整数(分)累加       = {total_cents / 100}")     # 100000.0 精确!
print()

# ====== 实验3: Decimal 构造方式的天壤之别 ======
print("Decimal(0.1)   =", Decimal(0.1))    # 0.10000000000000000555... 脏!
print("Decimal('0.1') =", Decimal("0.1"))  # 0.1 干净!
print()

# ====== 实验4: 大数吃小数 ======
print("1e16 + 1 =", 1e16 + 1)              # 1e16 (那个+1被"吃"掉了!)
print("精度不足以表示这么大的数+1的差别")
print()

# ====== 实验5: 必须用float时, 正确的比较方式 ======
import math
x = 0.1 + 0.2
print("x == 0.3:        ", x == 0.3)              # False
print("math.isclose:    ", math.isclose(x, 0.3))  # True ✓

# 核心: float累加100万次0.1得不到精确100000(误差累积), Decimal和整数都精确;
#   Decimal(0.1)脏、Decimal('0.1')干净; 大数吃小数; float比较用isclose。亲手跑一遍最深刻。

这段实验代码,把"float 之坑"和"Decimal/整数之解"变成了一行行可以亲眼验证的输出。它的精妙,在于用"累加 100 万次 0.1"这个极端场景,把平时藏在小数点后第 17 位、肉眼看不见的微小误差,累积、放大成一个明显的、非零的偏差——你会清清楚楚地看到:float 累加 100 万次 0.1,得到的不是精确的 100000.0,而是一个带着误差尾巴的数;而 Decimal 和整数(分)版,都精确地得到了 100000.0再加上 实验 3 对比 Decimal(0.1) 的脏和 Decimal("0.1") 的干净实验 4 的"大数吃小数"实验 5 的正确比较方式,这一组实验,几乎把浮点数的核心坑都"跑给你看"了。这,正是我想用这段代码,留给每个程序员的最后一课:对于浮点数精度这种"反直觉、且后果严重"的问题,最好的学习方式,就是亲手写一段实验,把那个"平时看不见的误差",通过极端场景(大量累加、大数小数)逼出来、放大到你眼前当你亲眼看着 float 累加 100 万次 0.1 得到一个"不对的数",这个坑就会以一种无法被遗忘的方式,刻进你的认知里。把"书上说的精度问题",变成"我亲眼跑出来的错误数字"——这种从"知道"到"见过"的跨越,是真正掌握一个反直觉知识点,最扎实可靠的途径而对于金钱这种"差一分都不行"的东西,这份"亲眼见过它会出错"的敬畏,值得每个工程师拥有。

写在最后

回头看,这场由"float 精度"引发的、对账差几分钱的事故,真正教给我的,远不止"金额用 Decimal"这一个技巧。它让我对"计算机里的数字"这个最最基础的概念,产生了一种全新的敬畏。我一直以为,"数字"是计算机里最简单、最可靠、最不会出错的东西——1 就是 1,0.3 就是 0.3,加减乘除天经地义。可这次事故狠狠地打破了这个幻觉:原来计算机里的"0.3",根本就不是数学上那个精确的 0.3,而是一个"无限接近、但并不等于"它的近似值;原来"0.1 + 0.2",在计算机里真的可以"不等于 0.3"。这种"连最基础的数字都靠不住"的认知冲击,让我领悟到一个深刻的道理:计算机里的一切,都是对现实世界的"有限的、近似的建模",而非现实本身;数字是对数学的近似(浮点)、字符是对文字的近似(编码)、时间是对时间的近似(时间戳/时区)……每一个我们习以为常的"基础类型",背后都是一套带着假设、带着局限、带着取舍的工程实现当我们"想当然地"把这些工程实现,等同于它们所建模的"理想概念"时(把 float 当成数学实数、把字符串当成文本),就会在它们"近似而非精确"的缝隙里栽跟头所以,真正扎实的工程能力,有很大一部分,来自于清醒地理解这些"基础抽象"的边界和代价:它在多大程度上忠实于它所建模的概念?又在哪些地方、为了什么(性能、空间)而做了妥协、留下了局限?不把抽象当现实、看清每个基础类型的"言外之意"——这,是我用一次"差几分钱"的事故,换来的、关于编程、也关于"基础抽象的边界"的、最朴素也最深刻的领悟。如果这篇复盘,能让你下次写金额计算时,条件反射地避开 float、用上 Decimal 或整数,那我对着那几分钱的差额熬的这大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我的 Agent 调用工具失败后,要么把报错信息当成正确结果继续往下编,要么对着同一个错误反复重试到耗尽,我对着工具错误处理排查了大半天的复盘

2026-6-2 7:11:46

技术教程

我用 == 判断一个值是否为空,结果空字符串、数字 0、空数组全被判成了"相等",逻辑全乱了,我对着 JavaScript 的隐式类型转换排查了大半天的复盘

2026-6-2 7:23:12

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索