2024年7月,一个简单的问题让全球十二个主流大模型中的八个栽了跟头:9.11和9.9哪个大?

这不是孤例。同样的问题还有:247 × 389等于多少?8743 + 3927呢?如果你尝试让ChatGPT、Claude或其他大模型直接计算这些数字,得到的答案往往令人哭笑不得——要么差几位数,要么完全离谱。

为什么一个能写诗、能编程、能通过律师资格考试的AI,却在小学二年级的算术题面前频频翻车?这个问题的答案远比"模型不够聪明"复杂得多。它涉及大模型如何看待数字、如何组织计算、以及神经网络架构本身的根本局限。

数字在大模型眼中长什么样

问题的根源始于一个看似简单的操作:tokenization。

大模型处理文本的第一步是把输入切分成token。对于自然语言,这个机制相当优雅——“unhappiness"会被切成"un”+“happiness”,“playing"变成"play”+“ing”,这种切分方式让模型能够理解词根和词缀的关系。

但数字的处理完全不同。

以GPT-2和GPT-3的tokenizer为例,数字的切分方式几乎毫无规律可循:

2249 → ["2", "249"]    # 1位 + 3位
2250 → ["22", "50"]    # 2位 + 2位
2251 → ["225", "1"]    # 3位 + 1位

这三个相邻的数字,被切成了完全不同的token组合。对模型而言,这意味着它无法建立一致的数字表示——2249和2250在token空间中的关系,与它们在数值空间中的关系毫无关联。

graph LR
    subgraph GPT-2/3 Tokenizer问题
        A["2249"] --> B["2, 249"]
        C["2250"] --> D["22, 50"]
        E["2251"] --> F["225, 1"]
    end
    
    B --> G["切分模式: 1位+3位"]
    D --> H["切分模式: 2位+2位"]
    F --> I["切分模式: 3位+1位"]
    
    style B fill:#ffcccc
    style D fill:#ffcccc
    style F fill:#ffcccc

更糟糕的是,训练语料中频繁出现的数字(如0-100、常见年份)往往获得独立的token,而罕见的大数字则被随机切割。这种不一致性迫使模型为每种切分方式学习特殊的处理规则,而非学习真正的算术算法。

Tokenizer的演进历程

timeline
    title Tokenizer处理数字方式的演进
    2020 : GPT-2/GPT-3时代 : 不一致的数字切分<br/>相邻数字切割模式不同
    2023 : Llama/Mistral : 逐位切分<br/>每个数字字符独立
    2024 : GPT-4/Claude : 三位一组切分<br/>按固定规则分块
    2024 : Claude创新 : 从右到左切分<br/>匹配加法自然顺序

2024年的一项系统性研究分析了不同tokenizer对算术能力的影响。研究者发现,当使用GPT-3的默认tokenizer(从左到右切分)时,模型在加法任务上的准确率显著低于强制使用逗号分隔(模拟从右到左切分)的情况。

为什么会这样?因为人类做加法是从右到左对齐数位的,而默认的tokenizer却把数字从左到右切割,导致模型难以识别数位的对齐关系。

新一代tokenizer的改进

意识到这个问题后,新一代模型采取了不同的策略。目前主要有两种方案:

逐位切分(Llama、Mistral、Gemma等):每个数字字符独立成token,即2164变成[“2”, “1”, “6”, “4”]。这种方式完全匹配人类的十进制表示,让模型能够学习标准的逐位算法。

三位一组切分(GPT-4、Claude等):把数字按三位一组切分,如216456变成[“216”, “456”]。这种方式的逻辑是:虽然需要学习1000个"原语"而非10个,但处理长数字时需要的步骤更少。一个9位数的加法,逐位方式需要9-10步,而三位一组只需要3-4步。

graph TD
    subgraph 逐位切分 - Llama系列
        A1["216456"] --> B1["2"]
        A1 --> B2["1"]
        A1 --> B3["6"]
        A1 --> B4["4"]
        A1 --> B5["5"]
        A1 --> B6["6"]
    end
    
    subgraph 三位一组 - GPT-4
        C1["216456"] --> D1["216"]
        C1 --> D2["456"]
    end
    
    subgraph 从右到左 - Claude
        E1["216456"] --> F1["456"]
        E1 --> F2["216"]
    end
    
    style B1 fill:#ccffcc
    style B2 fill:#ccffcc
    style B3 fill:#ccffcc
    style B4 fill:#ccffcc
    style B5 fill:#ccffcc
    style B6 fill:#ccffcc

有趣的是,Claude采用了从右到左的三位一组切分——这与加法的自然顺序一致。研究表明,这种策略确实提升了算术表现。

但即便解决了tokenization问题,大模型的算术能力仍然不尽如人意。这指向了更深层的原因。

神经网络真的在"计算"吗

2025年ICLR会议接收的一篇论文给出了一个令人意外的答案:大模型做算术,既不是用算法,也不是靠记忆,而是用一堆"启发式规则"拼凑出来的。

研究团队使用了因果分析技术,定位出模型中负责算术运算的神经元子集(一个"电路"),然后逐一分析这些神经元的功能。

结果发现,这些神经元各司其职,每个都在检测一个粗粒度的条件:

  • 范围启发式:检测结果是否落在某个区间(如150-180)
  • 模启发式:检测结果是否满足某个模条件(如结果mod 10 = 8)
  • 模式启发式:检测结果是否匹配某个正则表达式
  • 操作数相等启发式:检测两个操作数是否相等

以"226 - 68 = ?“为例,模型内部发生的事情是这样的:

第24层的神经元12439检测到结果在150-180之间,于是提升"150”、“151”…“180"这些token的概率。

第30层的神经元1582检测到结果mod 10 = 8,于是提升"8”、“18”、“28”…“998"这些token的概率。

graph TD
    A[输入: 226 - 68 = ?] --> B[神经元层24]
    A --> C[神经元层30]
    A --> D[更多神经元层...]
    
    B --> B1[神经元12439<br/>检测结果∈150,180]
    B --> B2[其他范围神经元...]
    
    C --> C1[神经元1582<br/>检测结果 mod 10 = 8]
    C --> C2[其他模神经元...]
    
    B1 --> E[概率提升:<br/>150,151...180]
    C1 --> F[概率提升:<br/>8,18,28...998]
    
    E --> G[Logits累加]
    F --> G
    D --> G
    
    G --> H[Softmax]
    H --> I[正确答案 158<br/>获得最多叠加提升]
    
    style I fill:#ccffcc

如此类推,数百个神经元各自贡献自己的判断。最终,正确答案"158"因为同时满足多个条件,获得了最多的"投票”,从而脱颖而出。

启发式神经元分类

graph LR
    A[启发式神经元] --> B[范围启发式]
    A --> C[模启发式]
    A --> D[模式启发式]
    A --> E[操作数相等启发式]
    A --> F[多结果启发式<br/>用于除法]
    
    B --> B1["检测结果∈a,b<br/>如: 150-180"]
    C --> C1["检测结果 mod n = m<br/>如: 结果 mod 10 = 8"]
    D --> D1["检测结果匹配正则<br/>如: 1.2形式"]
    E --> E1["检测op1 = op2"]
    
    style A fill:#e6f3ff
    style B fill:#fff3e6
    style C fill:#e6ffe6
    style D fill:#ffe6e6
    style E fill:#f3e6ff

这个发现解释了许多现象:

为什么大模型有时能算对,有时却错得离谱?因为这种"启发式袋"机制本身就不精确——如果某个错误答案恰好也满足多个条件,它就可能"骗过"模型。

为什么更大的模型算术能力更强?因为更大的模型有更多的神经元,能够学习更细粒度的启发式规则,提高答案的精确度。

为什么思维链(Chain of Thought)有效?因为把计算拆成多个步骤,相当于引入了更细粒度的启发式检查。

但这也意味着一个更深层的问题:大模型从未真正学会"算术"——它只是在模式匹配的层面上模拟计算过程。

正确答案与错误答案的神经激活对比

graph TD
    subgraph 正确案例
        A1["226 - 68 = ?"] --> B1[多个启发式神经元激活]
        B1 --> C1[正确答案158获得<br/>最多logit提升]
        C1 --> D1["输出: 158 ✓"]
    end
    
    subgraph 错误案例
        A2["其他计算"] --> B2[较少启发式神经元激活]
        B2 --> C2[正确答案logit提升不足]
        C2 --> D2["输出: 错误答案 ✗"]
    end
    
    style D1 fill:#ccffcc
    style D2 fill:#ffcccc

位置信息是如何丢失的

即使有了好的tokenizer和足够多的启发式神经元,大模型仍然面临一个架构层面的障碍:难以追踪数字中每一位的位置。

人类做加法时,需要知道"2164"中的"2"是千位,“1"是百位,以此类推。这种"位值"信息是算法的核心。

但Transformer的位置编码是为序列设计的,而非为数字设计。当你输入"2164 + 3827”,模型知道"2"是第1个字符,“1"是第2个字符,但它不知道"2"在这个数字中的"地位”(千位)。

graph LR
    subgraph 标准位置编码
        A["输入: 2164 + 3827"] --> B["位置: 1,2,3,4,5,6,7,8,9"]
    end
    
    subgraph 问题所在
        B --> C["模型知道字符顺序<br/>但不知道数位地位"]
        C --> D["'2'是第1个字符<br/>但它是千位还是个位?"]
    end
    
    style D fill:#ffcccc

2024年的一项研究提出了一个巧妙的解决方案:Abacus Embedding

这个方法的核心思想是为每个数字内部的位置分配一个特殊的位置嵌入。对于输入"2164 + 3827",模型会给每个数字分配连续的位置编码:

输入数字:  2  1  6  4  +  3  8  2  7
标准位置:  1  2  3  4  5  6  7  8  9
数字位置:  4  3  2  1  -  4  3  2  1  # 从右到左编号

这相当于给模型提供了"数位对齐"的线索。训练时,研究者还会随机偏移起始位置,让模型学会处理任意长度的数字。

Abacus Embedding的工作原理

graph TD
    subgraph 输入处理
        A["输入: 2164 + 3827"] --> B["Tokenize: 2,1,6,4,+,3,8,2,7"]
    end
    
    subgraph 位置编码
        B --> C["标准位置: 1,2,3,4,5,6,7,8,9"]
        B --> D["数字位置: 4,3,2,1,-,4,3,2,1"]
    end
    
    subgraph 嵌入组合
        C --> E[Token Embedding]
        D --> F[Abacus Embedding]
        E --> G[组合嵌入]
        F --> G
    end
    
    G --> H[模型能够理解<br/>数位对齐关系]
    
    style H fill:#ccffcc

结果令人惊叹:使用Abacus Embedding训练的模型,能够在训练数据最大20位数的情况下,正确计算120位数的加法——这是6倍的泛化能力,远超之前2.5倍的最佳记录。

长度泛化能力对比

graph LR
    subgraph 传统方法
        A1["训练: 20位数"] --> B1["测试: 50位数<br/>泛化: 2.5倍"]
    end
    
    subgraph Abacus Embedding
        A2["训练: 20位数"] --> B2["测试: 120位数<br/>泛化: 6倍"]
    end
    
    style B2 fill:#ccffcc

为什么这很重要

理解大模型算术困难的根源,不仅仅是为了解决"9.11和9.9哪个大"这种问题。它揭示了神经网络在处理需要精确算法的任务时的根本局限。

算法 vs 模式匹配

graph TD
    subgraph 传统计算机 - 算法执行
        A1["输入: 226 + 68"] --> B1["步骤1: 对齐数位"]
        B1 --> C1["步骤2: 逐位相加"]
        C1 --> D1["步骤3: 处理进位"]
        D1 --> E1["输出: 294<br/>确定性正确"]
    end
    
    subgraph 大模型 - 模式匹配
        A2["输入: 226 + 68"] --> B2["神经元群投票"]
        B2 --> C2["概率分布生成"]
        C2 --> D2["输出: 294<br/>概率性正确"]
    end
    
    style E1 fill:#ccffcc
    style D2 fill:#fff3e6

传统计算机执行加法时,使用的是确定性算法:按位对齐、逐位相加、处理进位。每一步都有明确的规则,每一步的结果都是精确的。

大模型执行加法时,使用的是概率性模式匹配:把问题映射到一个高维空间,让数百个神经元各自投票,最后取概率最高的答案。

这两种方式有本质区别。前者可以保证正确性,后者只能追求高准确率。前者可以泛化到任意长度的数字,后者受限于训练数据的分布。

这也是为什么大模型能通过复杂的法律考试,却在简单计算中翻车——法律推理本质上是模式识别和语言理解,而算术需要精确的算法执行。

不同任务的性质对比

graph LR
    A[任务类型] --> B[模式匹配型]
    A --> C[算法执行型]
    
    B --> D[自然语言理解]
    B --> E[代码生成]
    B --> F[创意写作]
    
    C --> G[算术计算]
    C --> H[逻辑推理]
    C --> I[精确验证]
    
    D --> J["大模型擅长 ✓"]
    E --> J
    F --> J
    
    G --> K["大模型受限 ⚠"]
    H --> K
    I --> K
    
    style J fill:#ccffcc
    style K fill:#fff3e6

实践中的启示

对于开发者而言,这些研究提供了几条明确的实践指南:

永远不要让大模型直接做精确计算。无论模型多么强大,它的底层机制决定了它无法保证计算的正确性。对于涉及财务、科学、工程的应用,必须使用专门的计算工具。

思维链可以改善但不能根除问题。让模型"一步步思考"或使用"草稿纸"确实能提高准确率,但这只是让启发式机制有更多步骤来筛选答案,而非让模型真正执行算法。

数值输入的格式很重要。如果你的应用需要处理大量数字,考虑使用逗号分隔、空格分隔等格式,帮助模型更好地切分数字。

选择合适的模型。处理数字密集型任务时,优先选择使用逐位切分tokenizer的模型(如Llama系列),或使用从右到左切分的模型(如Claude)。

技术演进的路径

认识到这些问题后,研究社区正在从多个方向寻求突破。

架构层面的改进

除了Abacus Embedding,研究者还探索了循环Transformer架构。通过让模型的某些层反复执行多次,可以更好地模拟算法的多步骤特性。

graph TD
    subgraph 标准Transformer
        A1[输入] --> B1[Layer 1]
        B1 --> C1[Layer 2]
        C1 --> D1[...]
        D1 --> E1[Layer N]
        E1 --> F1[输出]
    end
    
    subgraph 循环Transformer
        A2[输入] --> B2[Layer Block]
        B2 --> C2[循环执行]
        C2 --> D2[同一Block<br/>再次执行]
        D2 --> E2[...]
        E2 --> F2[输出]
    end
    
    style F2 fill:#ccffcc

实验表明,使用循环架构配合Abacus Embedding,可以将加法的准确率从94%提升到99%,错误率降低50%以上。

训练方法的改进

一种被称为"渐进式损失"的训练策略被证明有效:在训练过程中随机减少模型的循环次数,让模型学会用更少的步骤完成任务,从而提高泛化能力。

工具使用的集成

最务实的方案是承认大模型在精确计算上的局限,让它调用外部工具。

graph LR
    A[用户问题] --> B{需要精确计算?}
    B -->|是| C[调用计算工具]
    B -->|否| D[大模型直接处理]
    C --> E[返回精确结果]
    D --> E
    
    style C fill:#ccffcc
    style E fill:#e6f3ff

现代大模型已经广泛支持函数调用,可以在识别到计算需求时自动调用计算器或代码解释器。

这实际上是最合理的架构:大模型负责理解和规划,专门的计算引擎负责执行。就像人类在解决复杂问题时会使用计算器一样,AI也不必"徒手"完成所有任务。

改进效果总结

graph TD
    A[大模型算术改进方案] --> B[Tokenizer优化]
    A --> C[架构改进]
    A --> D[训练策略]
    A --> E[工具集成]
    
    B --> B1["逐位切分: 更一致的数字表示"]
    B --> B2["从右到左: 匹配加法顺序"]
    
    C --> C1["Abacus Embedding: 6倍泛化"]
    C --> C2["循环架构: 50%错误降低"]
    
    D --> D1["渐进式损失: 更好泛化"]
    D --> D2["思维链: 准确率提升"]
    
    E --> E1["函数调用: 精确保证"]
    E --> E2["代码解释器: 可验证结果"]
    
    style E fill:#ccffcc

更深层的思考

大模型算术困境揭示了一个关于人工智能的深层问题:语言能力是否等同于推理能力?

大模型在语言任务上的出色表现,让很多人产生了"模型在思考"的错觉。但算术这个简单的测试揭示了一个事实:模型可能只是在极其复杂的层面上进行模式匹配,而非真正理解问题背后的逻辑。

这并不意味着大模型没有价值。恰恰相反,模式匹配是一种极其强大的能力——它让模型能够理解语言、生成代码、进行创作。这些任务的共同特点是:它们不需要精确的算法,只需要合理的模式延续。

但对于那些需要精确性的任务——数学计算、逻辑推理、决策制定——我们需要更清醒地认识到模型的边界。不是所有问题都能用模式匹配解决,不是所有智能都来自语言。

理解这一点,才能更好地设计AI系统:让大模型做它擅长的事(理解、规划、生成),让专门的工具做它不擅长的事(计算、验证、执行)。这种"人机协作"的模式,或许比追求"通用人工智能"更务实,也更安全。

当被问及9.11和9.9哪个大时,正确答案不应该依赖模型的内部状态,而应该来自一个简单的规则:打开计算器,输入这两个数字,比较结果。这不是对AI的否定,而是对问题复杂性的尊重——有时候,最简单的方法才是最可靠的。

参考信源

  1. Singh et al. (2024). Tokenization counts: the impact of tokenization on arithmetic in frontier LLMs. arXiv:2402.14903.

  2. Nikankin et al. (2025). Arithmetic Without Algorithms: Language Models Solve Math with a Bag of Heuristics. ICLR 2025.

  3. McLeish et al. (2024). Transformers Can Do Arithmetic with the Right Embeddings. arXiv:2405.17399.

  4. Beren. (2024). Integer tokenization is now much less insane. beren.io

  5. Hugging Face. (2024). Number Tokenization Blog. huggingface.co

  6. Sato, R. (2026). How LLMs Really Do Arithmetic. Data Processing Club.

  7. Lee et al. (2023). Teaching Arithmetic to Small Transformers. arXiv.

  8. Zhou et al. (2024). Algorithms for Transformers. arXiv.

  9. Cobbe et al. (2021). GSM8K: Dataset for Grade School Math. arXiv.

  10. OpenAI. (2024). GPT-4 Technical Report.

  11. Anthropic. (2024). Claude 3 Technical Report.

  12. Meta. (2024). Llama 3 Technical Report.