LLM数学能力解析:为何擅长公式推导却算不对乘法? 如果你让一个普通大语言模型计算1234567 * 7654321它可能给出一个看起来毫无破绽、但最后几位完全错误的答案如果你让它对x^3 * sin(x)求导它反而能写得又快又规范。这种反差几乎每个使用过 LLM 处理数学问题的人都遇到过。围绕“LLM 到底擅长什么数学”技术社区里一直存在两派声音一派认为 LLM 就是“通用推理引擎”可以替代计算器另一派觉得 LLM 在数学上就是“一本正经地胡说八道”。这两种判断都太极端了。我更愿意把 LLM 的数学能力描述为擅长“规则可形式化、模式可记忆”的数学不擅长“需要精确数值计算、长链一致性验证”的数学。这篇文章会从 LLM 的底层机制出发分析它为什么会有这样的能力结构然后给出一个可以直接运行的 Python 评测脚本帮助你建立自己的数学能力测试集最后总结提升 LLM 数学能力的提示词策略、外部工具组合方式以及生产环境里的工程建议。读完你会得到一个清晰的结论在什么场景下可以让 LLM 直接做数学在什么场景下必须把它换成“代码执行器 符号计算库”。1. 为什么“LLM 擅长什么数学”值得认真讨论这几年大模型应用落地数学推理几乎是所有 Agent、RAG、数据分析场景绕不开的坎。做报表分析时要让 LLM 生成聚合公式做算法设计时希望它写出数值稳定的实现做教学工具时希望它能一步步解方程。一旦这些问题真的放到生产流程里你会发现模型不是全能的而大多数失败并不是模型“笨”而是任务类型选错了。一个常见的误区是开发者默认“LLM 的数学能力 计算能力”。于是让模型做高精度乘法、大数取模、矩阵求逆然后期待它像计算器一样返回精确结果。结果当然是失望。另一个误区是反向的因为模型算不对简单乘法就认为它在数学上一无是处连微积分推导、概率公式整理这种它真正擅长的工作也一起放弃了。这两个误区背后是缺少一个对“数学任务类型”的细分框架。数学不是一门单一的技能它至少可以拆成数值计算要求精确、可复现例如1234567 * 7654321。符号操作按照确定规则变换表达式例如求导、积分、代数化简。逻辑推理从公理出发推导命题例如几何证明、数论证明。算法设计设计求解问题的步骤例如排序、动态规划。概念理解用自然语言解释数学定义、定理、应用场景。LLM 在这五类任务上的表现差异非常大。如果不区分类型任何讨论都容易变成各说各话。本文的核心就是给出一个可操作的判断方法什么时候可以信任 LLM 的数学输出什么时候必须让代码和工具接管。2. LLM“做数学”的底层机制不是计算是生成要理解 LLM 的数学能力边界先要看它的底层工作方式。LLM 本质上是自回归语言模型给定前文预测下一个 token。这里的 token 可以是单词、子词也可以是字符块。对英文和代码而言常见 tokenizer 会把“1234567”切分成多个 token比如123、456、7。这意味着模型看到的不是一个完整的十进制整数而是被拆开的若干小片段。这种切分方式带来两个直接后果数字的“整体语义”是缺失的。人在计算1234567 * 7654321时会在脑内或纸上执行进位、对齐、乘法表。LLM 没有这样的执行器它只能在 token 序列的统计模式中寻找“看起来像答案”的序列。当数字变得很长训练数据里没有完全相同的例子时模型就只能靠局部的模式拼凑。错误会随长度累积。每一步生成都在选择概率最高的 token但每一步都存在出错可能。数学推理链条越长任何一步出现偏差后续所有步骤都会沿着错误方向继续。即使模型每一步的正确概率是 95%20 步之后整体完全正确的概率就只剩约 36%这也是长链数学推理容易翻车的数学原因。那为什么在求导、代数化简这类问题上LLM 表现得很好因为这些任务的“模式”在训练语料里出现了成千上万次。模型并不是真的在“计算”导数而是在复现它见过的解题范式幂函数求导降次、乘积法则、链式法则这些规则已经被语言化了。只要模型记住了规则并且输入表达足够标准它就能以“文字生成”的方式完成“符号推导”。所以更准确的理解是LLM 不是数学计算器而是一个**“数学语言模式的生成器”**。它生成的是“符合数学语法”的文本而不是“经过数学计算”的结果。两者之间有时高度一致有时完全不相关。工具类型数值计算符号操作概念理解算法设计长链证明传统计算器强弱无无无数学软件MATLAB/Mathematica/SymPy强强无部分弱LLM弱中强强强中弱LLM 代码执行器强强强强中弱这张表是本文最重要的判断LLM 的价值在“数学语言能力”而“数学计算能力”必须由工具补足。3. LLM 真正擅长哪些数学任务根据上面提到的机制我们可以归纳出 LLM 擅长的数学任务共性规则明确、模式重复、训练语料充足、表达形式贴近自然语言。具体包括以下几类。3.1 基础符号计算只要规则是标准化的模型通常能给出很好的结果。例如多项式求导、常见函数求导基础积分尤其是常见积分表内的形式代数方程化简、因式分解矩阵加减乘、转置、行列式符号规则清晰下面是一个典型例子。给模型提问对 f(x) x^3 * sin(x) 求导并用乘积法则写出步骤。常见的 LLM 通常会给出类似这样的回答这里只作示意设 u x^3v sin(x)则 u 3x^2v cos(x)。 由乘积法则f(x) uv uv 3x^2 sin(x) x^3 cos(x)。对。这个结果是正确的。为什么因为这种题目在教材、题解、学术网页中出现无数次模型只需要“回忆”解题模式不需要真正执行微积分运算。3.2 概率和统计中的公式推导概率论里很多题目表达方式接近应用题天然适合 LLM 的“自然语言理解”能力。比如“从 52 张牌中抽到红心的概率是多少”模型可以正确解释古典概型并列出13/52 1/4。它甚至能帮你把贝叶斯公式、条件概率、期望和方差的概念讲得比很多课本更清晰。这个领域要注意的是模型擅长概念解释和公式套用但不擅长处理复杂的分支计数、蒙特卡洛模拟和真实数据集上的统计计算。涉及精确组合数时建议用代码验证。3.3 算法设计与伪代码数学和算法是强相关领域。LLM 在“根据问题描述设计求解步骤”上非常强因为代码和算法题解法在网上有海量语料。你可以让模型设计一个二分查找的伪代码。给出动态规划的状态转移方程。解释一段数学公式如何转成可执行的 Python 代码。这个能力的产出是“设计”不是“执行”。模型给你伪代码你执行后验证正确性这是当前最稳妥、也最高效的协作方式。3.4 数学概念解释与教学LLM 最擅长的数学任务其实是“把数学讲成人话”。面对“什么是特征值”“什么是梯度下降”“为什么正态分布重要”这类问题它能给出层次分明、有比喻、有例子的回答。这对教学、技术文档、新手入门有极高价值。这里几乎不会遇到“算错”的问题因为输出是解释性文本而不是数值结果。如果再要求模型引用来源、给出反例可信度会进一步提升。4. LLM 不擅长什么数学以及背后的原因任何公开评测都显示LLM 在“精确数值计算”和“长链推理”上会稳定出错。这是机制问题不是提示词能完全解决的。4.1 大数精确乘法与多位小数比较训练数据里可能出现过123 * 456但不太可能出现过1234567890 * 9876543210这类随机组合。模型做不到“真正进位”所以结果往往在高位或低位出错。类似的还有小数比较。比如3.11和2.100哪个大对模型来说token 序列里出现了字符100比11长就可能错误判定后者更大。这是因为模型看到的并不是“小数点后等位对齐”而是“字符串长度和数值符号”的混合信号。4.2 复杂数论和组合计数涉及质因数分解、模运算、大数 gcd、组合数精确取值时LLM 如果直接口算非常容易给出错误的“看起来合理”的答案。原因是这些任务需要系统搜索和约减而不是模式匹配。模型可能会背下来一些常见组合数的值但只要参数稍作变化它就会开始胡编。4.3 多步形式化证明LLM 可以写出数学证明的“框架”但无法保证每一步逻辑都严格无损。它经常在推导过程中偷换假设或者把“要证明的结论”提前当作“已经成立的条件”。这本质上是长期依赖问题形式证明的每一个步骤都依赖之前的全部状态而自回归模型很难保持超过一定长度的全局一致性。4.4 为什么不建议让 LLM 直接做数值计算一句话总结LLM 没有“计算状态”。它只有“文本状态”。人类做乘法时有进位寄存做积分时有规则表。LLM 既没有寄存器也没有真正的规则表它所拥有的是“概率权重”。一旦任务需要多步状态更新模型就会在文本生成过程中丢失或混淆状态。所以更合理的用法不是逼模型把数学算对而是让模型负责“如何算”让代码负责“算出来”。5. 用代码建立一个 LLM 数学能力评测脚本前面讲了很多理论现在动手验证。下面这个 Python 脚本可以帮你对自己的模型服务建立一个小型数学能力测试集。你可以运行它观察 LLM 在算术、代数、概率三类问题上的表现并和标准答案对比。5.1 调用模型的公共函数这里以 OpenAI 兼容接口为例。如果你用的是其他服务只需要替换url、headers和payload里的模型名。# 文件路径evaluate_math_llm.py import requests def ask_llm(prompt: str, temperature: float 0.0) - str: 调用大模型服务。 请将 YOUR_API_KEY 替换为你的 API Key 将 your-model-name 替换为你实际使用的模型标识。 url https://api.openai.com/v1/chat/completions headers { Authorization: Bearer YOUR_API_KEY, Content-Type: application/json } payload { model: your-model-name, messages: [{role: user, content: prompt}], temperature: temperature } resp requests.post(url, headersheaders, jsonpayload, timeout60) resp.raise_for_status() return resp.json()[choices][0][message][content]注意这里的temperature0是为了尽量让模型输出稳定减少随机性。如果你在做创造性数学思路探索可以适当调高到 0.2~0.5但评测默认用 0。5.2 定义测试集和思维链提示词一个有效的测试集不需要很多题目但需要覆盖不同类型的数学任务。下面是精简版# 在 evaluate_math_llm.py 中继续添加 COUNTEREXAMPLE_PROMPT ( 请一步一步思考并在最后给出答案。 如果是数值计算请只输出最终数值。 如果不确定请明确说‘无法确定’。 ) tests [ { id: arithmetic_1, category: 精确算术, question: 1234567 * 7654321 ?, }, { id: algebra_1, category: 代数运算, question: 对函数 f(x)x^3*sin(x) 求导并用乘积法则写出步骤。, }, { id: probability_1, category: 基础概率, question: 掷两个六面骰子点数之和为 7 的概率是多少请写出计算过程。, }, ]这个测试集的三道题分别对应 LLM 的“弱项”“强项”和“中强项”。你可以打印出模型的回答直观感受它的差异。5.3 执行评测并打印结果# 在 evaluate_math_llm.py 中继续添加 def run_evaluation(): for test in tests: full_prompt test[question] \n COUNTEREXAMPLE_PROMPT print(f\n {test[id]} [{test[category]}] ) print(f题目: {test[question]}) print(LLM 回答:) try: answer ask_llm(full_prompt) print(answer) except Exception as exc: print(调用模型失败:, exc) if __name__ __main__: run_evaluation()然后运行python evaluate_math_llm.py运行后你可能会看到类似这样的现象probability_1的推导过程完整algebra_1的计算结果正确而arithmetic_1的数字很可能出错。这个结果本身就能说明问题。5.4 用 Python 验证正确答案为了对比我们可以用 Python 直接计算结果# 文件路径verify_with_python.py print(1234567 * 7654321 , 1234567 * 7654321)输出1234567 * 7654321 9449772114007你只要把 LLM 对arithmetic_1的答案和这个结果对比就会发现“生成式数学”和“计算式数学”之间的差距。这也是我在工程中最常用的验证方式凡是能代码计算的绝不依赖模型直接输出。6. 提升 LLM 数学能力的实用方法如果你确实需要在某些环节依赖 LLM 的数学推理以下方法能显著提高输出正确率。6.1 强制思维链并分解步骤让模型把中间过程写出来而不是直接给答案。这已经是公认有效的手段。如果你发现模型某个大题做不到就把它拆成几个小问题逐个问每问一步都校验一次中间结果。示例提示词请把求解过程分成 5 步 1. 整理已知条件 2. 列出需要使用的公式 3. 代入公式 4. 计算中间结果用 Python 表达式表示 5. 给出最终结论6.2 用 Few-shot 提供解题范式给模型一两个同类题的完整示例再让它做新题。特别是符号计算和概率题有个参照模板能大幅减少步骤错误。示例模板示例题目求 f(x) x^2 * e^x 的导数。 解答过程 设 u x^2, v e^x u 2x, v e^x f(x) uv uv 2x e^x x^2 e^x 现在请用同样的方式求f(x) x^3 * sin(x) 的导数。6.3 让模型写代码而不是“算答案”对于任何数值计算问题都改变提问方式。不要问“结果是多少”而是问“请写一段 Python 代码计算它并告诉我运行结果”。虽然模型生成的代码也可能有 bug但代码是可执行、可验证、可 debug 的比黑盒生成数字可靠得多。示例请用 Python 写一个程序计算 1234567 * 7654321并打印结果。然后你本地运行它得到准确答案。整个过程LLM 负责“生成算法”Python 负责“执行计算”。这是一个非常稳定的分工。6.4 引入符号计算库作为外部验证工具在需要严格符号推导的场景比如求导、积分、矩阵化简可以让 LLM 输出 SymPy 代码或者直接用 SymPy 验证它的推导结果。from sympy import symbols, diff, sin x symbols(x) expr x**3 * sin(x) result diff(expr, x) print(result) # 3*x**2*sin(x) x**3*cos(x)这种做法的价值是LLM 负责给你一个思路和方案SymPy 负责保证符号计算的正确性。如果两者不一致说明 LLM 的推导有问题而不是工具的问题。6.5 允许模型说“我不会”很多错误答案都来自模型“硬答”。在 prompt 里明确写如果这个问题需要精确数值计算且你无法保证结果正确请直接说‘该题建议使用代码执行器’不要编造数值。这会降低“一本正经胡说八道”的概率。在工程上我们可以把这样的回复当作一个“工具调用信号”让 Agent 自动切换到 Python 执行器。7. 常见问题与排查方法在实际使用中你可能遇到下面的现象。这里给出对应的排查方向。问题现象可能原因排查方式解决方案简单乘法算错tokenizer 把数字拆分模型没有真正进位把题目放到代码执行器或 Python 中验证用代码执行器计算不依赖模型直接给数推理步骤都对最后答案错误最后一步合并或代入出错检查最后 2~3 行推导要求模型分步输出并单独验证最后一步证明题过程像是“循环论证”模型把结论当成条件使用了对比每一步是否只使用前提和已证结论拆成原子步骤逐步检查逻辑依赖概率题概念对组合数算错组合数计数依赖系统搜索模型无法执行把组合数计算改写为 Python 代码调用math.comb或scipy.special.comb模型在不同 prompt 下答案不一致提示词空间不同推理路径不稳定固定 prompt 模板并评估多次对关键计算设置投票机制或人工复核答案很流畅但不符合常识约束模型在记忆类似题而不是验证数值增加“如果数值不合理请标记”约束增加规则校验器例如检查结果是否在合理区间排查的第一原则先看是“概念错误”还是“数值错误”。概念错误需要调整 prompt 或换模型数值错误则直接切换为代码执行这比任何提示词工程都有效。8. 生产环境中的工程建议如果你正在开发一个涉及数学计算的 LLM 应用下面这些工程实践能避免很多线上问题。8.1 把“数学推理”和“数值计算”拆成两条链路不要让模型既负责设计公式又负责计算结果。建议架构是LLM 负责理解问题、选择公式、设计求解步骤。代码执行器Python、JavaScript 等负责所有数值计算。符号计算库SymPy、Mathematica 等负责需要精确符号变换的任务。最终结果由代码执行器输出并回传给 LLM 组织成用户可读的答案。这种“LLM 生成 工具计算”的模式也是当前 Agent 应用的主流范式。它可以同时利用 LLM 的语义理解能力和计算工具的确定性。8.2 建立回归评测集为你的业务准备 50200 道典型数学题评测集覆盖数值计算、符号推导、应用题、概念解释。每次更换模型或修改 prompt 后跑一遍评测集对比正确率和格式一致性。这样就能避免“感觉新模型更强但某个线上场景突然变差”的问题。评测集不需要追求大而全关键是贴近真实用户提问。从我接触的项目经验看20 道高代表性题目往往比 100 道随机题更有用因为你可以逐个检查失败原因。8.3 对代码执行做安全隔离如果使用“LLM 生成代码并执行”的方式必须考虑安全风险。不要直接对 LLM 生成的代码调用eval()或exec()而是使用沙箱容器如 Docker 隔离。使用白名单函数库屏蔽文件、网络、子进程等能力。对执行资源做超时和内存限制。禁止执行任意系统命令。# 不推荐直接执行模型输出 # exec(model_output) # 推荐在受限环境中执行或仅提取表达式 import ast def safe_eval_math_expression(expr: str): 仅允许字面量、基本运算符和常见数学函数生产环境请使用真实沙箱。 tree ast.parse(expr, modeeval) allowed (ast.Expression, ast.BinOp, ast.UnaryOp, ast.Num, ast.Load, ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Pow, ast.Name, ast.Call) for node in ast.walk(tree): if not isinstance(node, allowed): raise ValueError(f不支持的语法: {type(node).__name__}) return eval(compile(tree, string, eval), {__builtins__: {}}, {})这段代码只是一个示例真正生产环境建议使用RestrictedPython或云函数隔离。这里的重点是LLM 生成的代码没有经过验证危险程度等同于执行不可信脚本。8.4 记录模型版本和 Prompt 版本数学能力对提示词非常敏感。同一个模型换几个字输出可能不同。建议在日志里记录模型名称和版本。Prompt 模板版本。temperature 参数。输入题目原文。输出结果。是否经过工具验证。这些日志可以用于线上问题回溯和评测集更新。8.5 人工复核高风险场景凡是涉及财务、医疗、安全决策的数学计算无论模型输出多么合理最终都必须由人工或权威计算工具复核。LLM 可以用作“草稿生成器”但不能作为“最终裁判”。这不是信不信任的问题而是工程安全边界的问题。9. 总结把 LLM 当成数学副驾驶而不是计算器回到标题本身“What sort of maths are LLMs good at?”我的答案是LLM 擅长那些可以被语言化、模式化、规则化的数学任务——公式推导、概念解释、算法设计、基础概率建模它不擅长需要精确计算、长链一致性和系统搜索的任务——大数乘法、组合枚举、严格证明。前者是“数学语言”后者是“数学计算”。LLM 生在语言世界长在统计模式它的强项在世界里弱项在符号的执行中。对开发者来说最优策略不是寻找一个“数学很强的模型”而是设计一套“不给模型硬算机会”的流程模型负责生成方案代码和符号库负责计算结果评测集负责兜底。如果你想实践今天提到的内容可以从两个动作开始一是用第五节脚本跑一遍你自己的模型记录它在算术、代数、概率三类问题上的表现二是把第一个“必须精确计算”的业务场景改造成“LLM 输出计算表达式Python 执行后返回结果”。做完这两步你会对“LLM 能做哪些数学”建立起自己的实证判断而不再依赖网上的碎片化评测。