news 2026/8/30 19:36:03

拿走计算器后,50个LLM原生算术能力评测揭秘

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
拿走计算器后,50个LLM原生算术能力评测揭秘

你有没有遇到过这种场景:一个日常对话、写代码、整理文档都很顺手的 LLM,却会在“9.11 和 9.8 哪个大”这种问题上翻车,或者算不对“23 × 47”?

很多开发者第一反应是换更强的模型,但真正的问题不在模型名字,而在“计算方式”。最近开发社区里出现了一个很有意思的实验,标题叫“Show HN: I took the calculator away from 50 LLMs and graded the arithmetic”,大意是:把计算器从 50 个 LLM 手里拿走,然后统一给它们的原生算术能力打分。这里说的“计算器”,指的是代码解释器、外部工具调用、Python 环境这一类辅助手段。拿走之后,模型只能靠自己的参数和注意力机制去算数。

这篇文章想借这个实验聊三件事:LLM 的算术能力为什么这么不稳定;这种“给模型做算术体检”的评测方法怎么设计;以及在真实 LLM 应用开发里,我们到底该怎么处理数学计算,是继续复用工具、还是调提示词、还是干脆换成规则代码。

1. 这个实验到底在测评什么

先搞清楚实验的核心问题:当 LLM 没有外部计算工具时,它的原始算术能力到底有多强?

这里有三个关键词:

  • 50 个 LLM:实验覆盖了主流闭源模型和多个开源模型,覆盖面比较广。
  • 计算器:这是一个很形象的比喻,泛指所有能帮模型“算准数”的外部工具。在很多 Agent 架构里,LLM 负责推理,计算器负责精确计算。
  • 打分:不是看模型写得对不对,而是看最终算术答案本身的标准答案命中率。

这个实验的实际背景,是很多 LLM 应用开发团队在接入 Agent 时遇到的问题:当前端工具链一旦被禁用,模型的计算能力就会迅速退化。“能力退化”不是指模型变笨了,而是指模型本身就不是一个稳定的计算器。

所以这个实验的实践价值是:

  1. 它让我们对“模型自带算术能力”有一个基线认知。
  2. 它告诉我们,模型在纯文本模式下的计算容错率并不高。
  3. 它提示我们,在 LLM 应用落地时,是否给模型配计算工具、配到什么程度,是会直接影响业务正确率的。

2. 为什么 LLM 会算错“简单算术”

很多人把 LLM 当计算器用,这是对 LLM 工作原理的误解。

LLM 不是计算机,而是一个概率语言模型。它在生成下一个 Token 时,并不是在“执行一段算术程序”,而是在根据上下文分布,选择最有可能的文本片段。

2.1 Token 级别的离散表示

数字在转成 Token 时,就会被切碎。比如“9.11”可能被切为9.11,而“9.8”可能被切为9.8。模型看到的并不是两个浮点数,而是两个文本序列。它需要从训练数据中学到“9.8 > 9.11”这个结论,而不是天然就知道浮点数比较规则。

这就像你给一个外国人看中文数字“九点八”和“九点一一”,他能读懂字符,但很难在潜意识里瞬间完成小数比较,只有学过特定换算规则之后才能稳定判断。

2.2 概率生成,而不是符号运算

当模型计算23 × 47时,它会根据训练数据里的海量算术题,生成一个“看起来合理”的答案。它没有像 CPU 那样执行乘法指令,而是模拟了“推导乘法结果”这个文本生成过程。

所以当算术步骤越长、进位越多时,错误概率就会指数级上升。这不是某一个模型的 bug,而是所有自回归语言模型的结构性瓶颈。

2.3 注意力窗口与中间错误传播

在多步计算中,模型需要记住中间结果。比如计算(12 + 34) × (56 - 23),它需要先算括号,再算乘法。每一步的输出都会影响下一步的判断,只要中间某一步出现偏差,后面就会跟着错。

这种错误传播和人类心算很像。人类在多步计算时也会写草稿,而 LLM 在纯文本模式下没有“草稿纸”,只能把所有中间状态压进上下文注意力中。上下文越长,注意力被稀释,早期计算结果就越容易被遗忘。

3. 评测设计:怎么给 50 个模型做同一套算术卷子

要评测不同模型的算术能力,首先要有一个统一的、可复现的评测方案。这里梳理一个通用的评测流程,你在自己项目里也能直接套用。

3.1 定义算术题集

算术题不能只测加法,否则看不出模型的差异。推荐按难度和类型分几个维度:

题型说明示例
整数加法两位数之间或三位数之间123 + 456
整数减法涉及借位1000 - 384
整数乘法两位数乘法23 × 47
整数除法除不尽和除得尽144 ÷ 12
小数运算浮点数加减乘0.1 + 0.2
小数比较容易混淆的比较题9.11 和 9.8 谁大
多步混合运算括号与优先级(12 + 34) × (56 - 23)
百分比题实际场景数值800 的 15% 是多少

每个类型建议准备 20 到 30 道题,题目数量太少无法区分模型差异,数量太多会放大低概率抖动。

3.2 统一提示模板

提示词对 LLM 数学能力影响非常大。评测时,最好是所有模型使用完全相同的模板,不要给某个模型额外“剧透”。

推荐模板:

请计算下面这道题。只用文字和心算,不要调用任何外部工具。 题目:{question} 输出格式:先给出最终结果,再简单说明计算过程,但最终结果请单独放在一行:答案:{{number}}

这里要用“心算”这个表述来模拟“拿走计算器”的场景,同时要求单独输出答案行,方便脚本解析。

3.3 采样参数

评测算术能力时,模型输出的随机性必须压制:

  • temperature = 0,尽量让输出稳定。
  • top_p = 1,不截断候选分布。
  • max_tokens设为 256 到 512,足够输出计算过程。
  • 关闭工具调用、代码解释器、函数调用等一切外部能力。

如果条件允许,每个题目可以跑 3 次,用多数投票作为最终答案。但在评测“原生算术”场景中,更严格的做法是只跑一次,因为这样才能模拟真实用户的使用体验。

3.4 评分方式

评分不能只看字符串是否完全相等,因为模型可能输出23*47=1081,也可能输出1081.0,甚至可能输出一千零八十一

推荐统一解析方案:

  1. 从输出里提取答案行。
  2. 把答案中的中文数字转阿拉伯数字。
  3. 去除空白和末尾.0
  4. 与标准答案做数值比较。
  5. 同时记录是否回答了“计算过程”,用于观察模型的推理结构。

4. 评测代码:如何用脚本跑一遍“算术体检”

下面提供一个可直接使用的 Python 评测脚本,遵循的是 OpenAI SDK 的写法。如果你用的是其他模型服务,只需要替换base_url和模型名。

4.1 基础评测脚本

# eval_arithmetic.py import json import re from openai import OpenAI # 不同模型服务只需要改 base_url 和 api_key client = OpenAI( base_url="https://api.openai.com/v1", api_key="YOUR_API_KEY", ) PROBLEMS = [ {"id": 1, "category": "add", "question": "123 + 456 = ?", "answer": "579"}, {"id": 2, "category": "sub", "question": "1000 - 384 = ?", "answer": "616"}, {"id": 3, "category": "mul", "question": "23 × 47 = ?", "answer": "1081"}, {"id": 4, "category": "div", "question": "144 ÷ 12 = ?", "answer": "12"}, {"id": 5, "category": "decimal", "question": "0.1 + 0.2 = ?", "answer": "0.3"}, {"id": 6, "category": "compare", "question": "9.11 和 9.8 谁大?", "answer": "9.8"}, {"id": 7, "category": "mixed", "question": "(12 + 34) × (56 - 23) = ?", "answer": "1518"}, {"id": 8, "category": "percent", "question": "800 的 15% 是多少?", "answer": "120"}, ] def normalize_answer(text: str) -> str: """归一化答案,去掉逗号、空格、中文数字等。""" text = text.strip() # 中文数字简单映射,只覆盖常见写法 cn_map = { "零": "0", "一": "1", "二": "2", "两": "2", "三": "3", "四": "4", "五": "5", "六": "6", "七": "7", "八": "8", "九": "9", } for k, v in cn_map.items(): text = text.replace(k, v) text = re.sub(r"[,\s,。]", "", text) text = re.sub(r"\.0$", "", text) return text def extract_answer(output: str) -> str: """优先找 答案: 这一行,没有就取最后一行数字。""" match = re.search(r"答案:([^\n]+)", output) if match: return normalize_answer(match.group(1)) nums = re.findall(r"[-+]?\d+\.?\d*", output) if nums: return normalize_answer(nums[-1]) return "" def evaluate_model(model_name: str, problems: list, temperature: float = 0.0): results = [] correct = 0 for p in problems: prompt = f"""请计算下面这道题。只用文字和心算,不要调用任何外部工具。 题目:{p['question']} 输出格式:先给出最终结果,再简单说明计算过程,但最终结果请单独放在一行:答案:{{number}}""" try: resp = client.chat.completions.create( model=model_name, temperature=temperature, messages=[{"role": "user", "content": prompt}], ) output = resp.choices[0].message.content or "" except Exception as e: output = f"ERROR: {e}" answer = extract_answer(output) is_correct = normalize_answer(p["answer"]) == answer if is_correct: correct += 1 results.append({ "id": p["id"], "category": p["category"], "question": p["question"], "expected": p["answer"], "actual": answer, "correct": is_correct, "output": output, }) return { "model": model_name, "total": len(problems), "correct": correct, "accuracy": correct / len(problems), "results": results, } if __name__ == "__main__": report = evaluate_model("gpt-4o", PROBLEMS) print(json.dumps(report, ensure_ascii=False, indent=2))

4.2 批量评测多个模型

如果你要评测多个模型,可以写一个简单的批量脚本,把模型名放进列表,逐个跑。

python eval_arithmetic.py --model gpt-4o --model claude-3-5-sonnet --model deepseek-chat

如果你的代码还没支持命令行参数,可以用下面这种方式包装:

# run_evals.py from eval_arithmetic import PROBLEMS, evaluate_model import json models = ["gpt-4o", "claude-3-5-sonnet", "deepseek-chat"] reports = [] for model in models: print(f"evaluating {model} ...") reports.append(evaluate_model(model, PROBLEMS)) with open("arithmetic_report.json", "w", encoding="utf-8") as f: json.dump(reports, f, ensure_ascii=False, indent=2) print("done.")

4.3 评测时的环境配置

为了避免 API 调用中断,建议把配置文件单独抽出来:

# config.yaml eval: temperature: 0 top_p: 1 max_tokens: 512 samples_per_problem: 1 models: - name: gpt-4o base_url: https://api.openai.com/v1 temperature: 0 - name: deepseek-chat base_url: https://api.deepseek.com/v1 temperature: 0 - name: qwen-plus base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 temperature: 0

如果你测试的是本地开源模型,也可以用 vLLM 或 Ollama 起一个 OpenAI 兼容服务,然后把base_url指向本机地址。

5. 这类评测中常见的规律

虽然这台“50 个模型算术横评”的具体排名和原始得分需要以作者公开的数据为准,但如果你按上述方法自己跑一遍,会看到很多在其他类似评测中反复出现的规律。

5.1 加法减法相对稳定,乘除法快速下降

大多数模型在两位数的加减法上表现尚可,因为训练数据里这类题目太多,模型已经形成了比较稳定的模式。但一旦进入两位数乘法、多位数除法,错误率会明显上升。位数越多,进位越多,错误率越高。

背后的原因不难理解:加法减法可以靠模式记忆兜底,乘除法需要真正的逐步运算能力,而自回归生成又放大了中间错误。

5.2 小数比较是一个“经典陷阱”

小数比较题,比如9.11 和 9.8 谁大,非常容易把模型带偏。因为模型遇到“9.11”和“9.8”时,第一反应可能是比较数字字符串的长度,或者调用训练数据中的“0.11 vs 0.8”模式,而不是把两者统一到同一精度下再比较。

这其实涉及一个更深层的问题:LLM 在训练时并不会专门针对浮点数比较做符号化处理,它的向量空间里,“9.11”和“9.8”的表示距离并不等同于它们在实数轴上的距离。

5.3 多步混合运算容易中途崩掉

(12 + 34) × (56 - 23)这类题目,模型需要先算46 × 33。很多模型会把第一步算错,或者把运算优先级搞错。即使模型给出了完整的推导步骤,最后一步也可能因为前面某个小错而全盘皆输。

所以评测时,不能只看最终答案,还要看过程。如果一个模型经常在推导过程正确的情况下算错最终结果,说明它在算术执行环节有问题;如果推导过程就已经错了,说明它的步骤分解能力不足。

5.4 模型规模不一定等于算术能力

开源模型社区里有一个常见误解:参数量越大,算术越准。实际上,算术能力同时受数据分布、训练策略和推理 prompt 影响。有的小模型通过精心构造的指令微调,在特定算术题型上反而比大模型更稳;但在未见过的新题型上,大模型的泛化能力通常更强。

因此,在选型时不要只看排行,要拿你们业务里真实出现的算术题型去测。

6. 别把“模型精度”和“算术精度”搞混

这个话题正好可以引入一个高频搜索词:LLM大模型之精度问题(fp16,fp32,bf16)详解与实践

很多开发者在看到“LLM 算数不准”时,第一反应是模型精度不够,于是去找 FP16、BF16 的量化参数。这其实混淆了两个精度概念:

  • 模型权重精度:指模型参数用 FP32、FP16 还是 BF16 存储。它影响模型推理时的内存占用和数值稳定性,但不会直接决定“9.11 和 9.8 谁大”这种问题。
  • 算术正确率:指模型输出和标准答案的一致性。它主要取决于模型本身的推理能力、训练数据和提示词。

为了理解权重精度,可以看这张表:

类型指数位尾数位典型范围说明
FP32823±3.4e38训练时最稳定,但显存占用高
FP16510±65504推理加速明显,但小数值容易损失精度
BF1687同 FP32指数范围大,尾数精度低,训练时常用

有些模型在部署时用 INT8 或 INT4 量化,推理速度提升明显,但算术能力可能略微下降。这是因为量化本质上是对权重做了有损压缩,极端情况下会让模型对细微数值模式的记忆变得模糊。

但在实际项目中,如果一个模型在 FP32 下也算不对9.11 vs 9.8,切换成 BF16 并不会修复这个问题。真正的修复手段是给模型配一个计算器,也就是外部工具。

7. 给 LLM 应用开发的落地建议

“拿走计算器”这个实验最大的现实意义,是提醒开发者在做 LLM 应用时,不要把算数这件事交给模型的“心算”。以下是生产中更稳妥的做法。

7.1 能走工具就不走参数

在 Agent 架构里,计算器应该是独立服务,而不是模型能力的一部分。当模型需要精确计算时,让它生成一段 Python 代码或调用一个计算函数。

输入 -> LLM(拆分任务)-> 识别出“需要精确计算” -> 调用计算函数/代码解释器 -> 拿到结果 -> LLM 整理输出

这样,LLM 负责的是语义理解和流程编排,计算器负责的是数值准确性。

# calculator_tool.py def calculate(expression: str): import ast import operator as op # 安全计算器:只允许白名单运算符 allowed_ops = { ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv, ast.Pow: op.pow, ast.USub: op.neg, } def eval_node(node): if isinstance(node, ast.Constant): return node.value if isinstance(node, ast.BinOp) and type(node.op) in allowed_ops: left = eval_node(node.left) right = eval_node(node.right) return allowed_ops[type(node.op)](left, right) raise ValueError("unsupported expression") return eval_node(ast.parse(expression, mode="eval").body)

注意,这里用了ast解析而不是eval,并且只允许白名单运算符,可以避免用户输入注入恶意代码。

7.2 用提示词鼓励“先列步骤再计算”

如果确实没有外部工具,可以引导模型把计算过程拆开。

请按以下步骤计算: 1. 先列出需要用到的数值 2. 写出每一步的中间结果 3. 最后给出最终答案 题目:23 × 47

这种“思维链提示”能显著提高模型的算术正确率,因为它把隐式的计算过程显式化,降低了中间错误传播的概率。但要注意,思维链不是万能的,它只改善推理过程,不改变模型对浮点数比较的固有弱点。

7.3 加一个校验器

在业务系统里,最稳妥的方案是加一个后置校验模块。模型输出的最终结果,如果是一个数值,先被校验器检查一次,再返回给用户。

7.4 根据题型选择模型

如果是聊天、摘要、写作类任务,可以追求语言流畅度,模型算术能力弱不影响体验。但如果是数据报表、金融计算、数学题解答类任务,应该优先选择:

  • 能稳定调用代码解释器的模型服务。
  • 经过数学指令微调的专用模型。
  • 自带工具调用能力的 Agent 框架。

在实际选型时,先跑一遍算术测试,再对比价格和延迟,比单纯看排行榜更靠谱。

8. LLM 算术能力相关常见问题与排查

在项目里接入 LLM 做算术,经常会遇到一些看起来很“玄学”的问题。下面整理一个排查表,按比例覆盖常见场景。

问题现象可能原因排查方式解决方案
同一个问题有时对有时错temperature 设置过高检查采样参数设置 temperature=0,或增加多数投票
简单加减法都对,乘法全崩训练数据中乘法样本分布不足用乘法题集做专项测试引入代码工具或微调专用模型
数值比较总是错小数比较的 token 表示异常打印模型的输出 Token换一种表达方式,如“9.8 是否大于 9.11,回答是或否”
多步计算中间步骤出错注意力被长上下文稀释检查模型输出过程分步提示,强制作答前先列出中间结果
用代码解释器能答对,关掉就错模型依赖外部工具做计算对比开关工具时的准确率判断业务是否需要工具兜底,需要则保留
量化后算术能力下降权重精度损失对比 FP32 与 INT8 输出关键服务保留 FP16 或 BF16,不要过度量化
模型说“我会算”,但结果错误指令跟随与计算执行不一致看最终答案位置和格式使用答案抽取脚本,并校验数值格式

很多问题的共同点,都是开发者默认了“模型输出等于系统输出”。在实际工程里,模型输出只是一个中间状态,至少要经过解析、校验和格式化,才能暴露给用户。

9. 从这次实验里,我们应该带走什么

“把计算器拿走”这个实验,真正值得关注的地方不是排行榜上谁第一谁第二,而是它用一种很简单的方式,把 LLM 的边界暴露在了我们面前。

LLM 的算术能力,本质上是语言模型在大量文本中“学到”的一种近似能力,而不是像计算机那样由 CPU 指令直接执行的结果。它可以在很多日常场景中表现很好,但在需要精确数值计算的地方,它并不稳定。

对开发者来说,这个结论直接对应三种工程策略:

  1. 如果算术只是辅助,正确性要求不高,可以靠 prompt 和思维链提升表现。
  2. 如果算术是业务核心,正确性要求高,必须引入外部计算工具,而不是指望模型心算。
  3. 如果模型要在受限环境里运行,不能调用工具,那就需要提前做算术专项测试,而不是上线后再排查。

建议你按上面第 4 节的代码,把你当前正在用的模型跑一遍,保存一份“算术体检报告”。以后每次换模型、换量化精度、改 prompt 模板,都重新跑一次,你会很早就发现问题,而不是等到用户反馈才知道。

更长期来看,大模型的发展方向一定是“推理 + 工具”的组合,而不是让参数里塞满所有计算能力。Agent 的一个重要价值,就是让 LLM 专注于理解任务,把精确计算委托给适合的工具。这也是为什么“LLM 应用开发”和“LLM Agent 编排”会成为整个生态里越来越重要的话题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 19:35:36

DisplayWave:开源macOS显示管理工具,轻松解决外接显示器痛点

DisplayWave 是一个以 Show HN 形式出现在 Hacker News 上的开源项目,定位很直接:给 Mac 用户做一个好用的显示管理工具。作者在标题里写了两个关键词——open-source 和 simple。这基本说明了它的立场:不是闭源商业工具,而是希望…

作者头像 李华
网站建设 2026/8/30 19:21:13

Obsidian 报错 Vault not found解决方案

1. 背景说明摘要:本文记录了 Obsidian Web Clipper 剪藏插件报错 Vault not found 的完整排查与解决过程。文章先介绍安装环境,再重点讲解如何提前创建并正确配置 Obsidian Vault(知识库),随后演示 Web Clipper 的安装…

作者头像 李华
网站建设 2026/8/30 19:17:53

FreeRTOS任务相关API函数

一、FreeRTOS任务相关API函数介绍 任务相关的API主要如下: 函数 描述 uxTaskPriorityGet() 获取任务优先级 vTaskPrioritySet() 设置任务优先级 uxTaskGetNumberOfTasks() 获取系统中任务的数量 uxTaskGetSystemState() 获取所有任务状态信息 vTaskGetIn…

作者头像 李华
网站建设 2026/8/30 19:17:34

Stable Diffusion实战:从男生照片生成女生形象并与兄弟同框合影

男人变成性感美女的样子跟好兄弟走在了一起?第一次看到这个需求,我还以为是个搞笑段子。但仔细拆解一下,这其实是一个很典型的 AI 创意图像生成项目:把人脸做“性别变换”,再让变换后的形象与另一个真实人物生成同框合…

作者头像 李华
网站建设 2026/8/30 19:15:35

上半年动力储能电池销量暴涨48.6%、小鹏机器人融资9亿美元、新型储能入列十五五:新能源产业的第二增长曲线

新能源车卖得慢了,但新能源产业的故事远没有结束。电池、储能、机器人,三条线同时传来新信号——它们正在成为继整车之后,中国新能源的又一条增长曲线。 动力储能电池销量暴涨48.6%,储能成最强引擎 先看最硬的数据。中国汽车动力电…

作者头像 李华
网站建设 2026/8/30 19:15:24

2026年AI数字人城市合伙人怎么选|3个维度避开合作陷阱

一、摘要AI 数字人赛道正在爆发。艾媒咨询数据显示,2025 年中国数字人核心市场规模达 480.6 亿元,带动周边市场突破 6400 亿元,预计 2026 年核心市场规模将扩大至 572.9 亿元。越来越多有客户资源、有渠道的老板想通过 AI 数字人城市合伙人切…

作者头像 李华