ZhiTu Ledger Vibe Coding实战(二):当AI第一次写出Bug算法,我是怎么让它自我修正的
AI生成的代码不一定对但如果你知道怎么“喂”Prompt它能自己修好自己。引子一个“能用但有Bug”的算法上篇文章发了之后很多人问我“AI写的代码真的靠谱吗”我的回答一直是“看情况。CRUD很稳但算法会翻车。”翻得最惨的一次是旅行账本的AA结算贪心算法。AI第一次给我生成的代码运行结果正确——A转B 100块B转C 50块账是平的。但如果你仔细看会发现转账次数不是最优的。明明可以3次搞定它给你算出来5次。问题是这个BugAI自己发现不了。因为它的代码逻辑是自洽的没有语法错误没有运行时异常甚至测试用例都能过——只要你给的不是“最优解验证”的测试。这就是Vibe Coding最危险的地方AI能写出“看起来对”的代码但不一定是“最好”的代码。这篇文章我把这次“算法翻车→手工推演→Prompt修正→最终验证”的全过程拆开来讲。希望对正在用AI写代码的人有帮助。一、需求回顾旅行AA要解决什么问题场景很简单5个人去旅行期间有人垫付饭钱、有人买门票、有人付打车费。旅行结束需要算清楚谁该转给谁多少钱并且转账次数越少越好。为什么转账次数要最少想象一下5个人的账如果每次都是两两结算最多可能有20笔转账。但最优方案可能只需要3-4笔——省事也省手续费。输入每笔消费记录包含付款人、金额、参与分摊的成员列表。输出转账指令列表格式为“A → BXX元”转账次数最少。二、AI的第一版实现看着没问题实际有坑我给的初始Prompt“实现旅行AA结算功能。输入所有消费记录输出谁该转给谁多少钱。要求转账次数最少。”AI生成的伪代码简化版publicListTransfersettle(ListExpenseexpenses){// 1. 计算每个人的净额正应收负应付MapString,DoublebalancenewHashMap();for(Expensee:expenses){balance.put(e.payer,balance.getOrDefault(e.payer,0)e.amount);doublesharee.amount/e.participants.size();for(Stringp:e.participants){balance.put(p,balance.getOrDefault(p,0)-share);}}// 2. 把净额拆成债权人和债务人两个列表ListPersoncreditorsbalance.entrySet().stream().filter(e-e.getValue()0).map(e-newPerson(e.getKey(),e.getValue())).sorted((a,b)--Double.compare(a.balance,b.balance)).collect(Collectors.toList());ListPersondebtorsbalance.entrySet().stream().filter(e-e.getValue()0).map(e-newPerson(e.getKey(),-e.getValue())).sorted((a,b)--Double.compare(a.balance,b.balance)).collect(Collectors.toList());// 3. 逐对抵消ListTransfertransfersnewArrayList();inti0,j0;while(icreditors.size()jdebtors.size()){Personccreditors.get(i);Personddebtors.get(j);doubleamountMath.min(c.balance,d.balance);transfers.add(newTransfer(d.name,c.name,amount));c.balance-amount;d.balance-amount;if(c.balance0)i;if(d.balance0)j;}returntransfers;}这个代码看着挺合理吧遍历所有消费、算净额、然后债权人和债务人逐对抵消。语法正确逻辑自洽运行也不报错。但它有个致命问题它没有考虑“谁先抵消谁”的策略只是按列表顺序依次抵消导致转账次数不是全局最优的。三、翻车现场一个手算就能发现的反例测试数据5个人A、B、C、D、E旅行消费记录如下消费付款人金额参与人晚饭A100A、B、C、D、E均摊门票B50B、C、D均摊打车C30C、D、E均摊手算结果先算每个人净额单位元成员付了多少该摊多少净额A10020晚饭均摊80应收B5020晚饭 16.67门票均摊13.33应收C3020晚饭 16.67门票 10打车-16.67应付D020晚饭 16.67门票 10打车-46.67应付E020晚饭 10打车-30应付最优转账方案3笔D → A46.67元E → A30元C → B16.67元共3笔转账账全部平掉。AI的方案按列表顺序抵消AI把债权人按金额从大到小排[A(80), B(13.33)]债务人按金额从大到小排[D(46.67), E(30), C(16.67)]。逐对抵消A vs D → A收46.67A剩余33.33A vs E → A收30A剩余3.33A vs C → A收3.33C剩余13.34因为A只有3.33了B vs C → B收13.33C剩余0共4笔D→A、E→A、C→A3.33、C→B13.33账是平的但多了1笔转账而且有一笔C→A的3.33元在实际旅行场景里非常尴尬——为了3块钱转一次账还不够手续费。关键是AI自己完全意识不到这个问题。四、调试过程怎么让AI发现并修正Bug4.1 第一轮直接指出问题我先把上面那个反例喂给AI“你的算法对于以下数据会输出4笔转账但最优解是3笔。请优化。”AI的回答是“我理解了我调整一下循环逻辑在每次抵消后重新排序。”然后它生成了新代码——在每次抵消后重新排序债权人和债务人列表确保总是让最大的债权人先处理。结果还是4笔。因为它只是重新排序了但仍然是“逐个抵消”的策略没有解决根本问题。4.2 第二轮给出策略方向我意识到它需要的是策略描述而不是Bug报告。“不要用‘顺序抵消’的思路。改用‘贪心策略’每次找到最大的债权人和最大的债务人用他们俩抵消。这样能保证每次消除掉最大的不平衡从而最小化总转账次数。”这一次AI理解了方向重新生成了代码publicListTransfersettleGreedy(MapString,Doublebalance){// 使用最大堆PriorityQueue存放债权人和债务人PriorityQueuePersoncreditorsnewPriorityQueue((a,b)-Double.compare(b.balance,a.balance));PriorityQueuePersondebtorsnewPriorityQueue((a,b)-Double.compare(b.balance,a.balance));// 填充两个堆for(Map.EntryString,Doubleentry:balance.entrySet()){if(entry.getValue()0)creditors.offer(newPerson(entry.getKey(),entry.getValue()));elseif(entry.getValue()0)debtors.offer(newPerson(entry.getKey(),-entry.getValue()));}ListTransfertransfersnewArrayList();while(!creditors.isEmpty()!debtors.isEmpty()){Personccreditors.poll();// 最大的债权人Personddebtors.poll();// 最大的债务人doubleamountMath.min(c.balance,d.balance);transfers.add(newTransfer(d.name,c.name,amount));c.balance-amount;d.balance-amount;// 如果还有剩余放回堆中if(c.balance0.001)creditors.offer(c);if(d.balance0.001)debtors.offer(d);}returntransfers;}这次改成了用最大堆PriorityQueue每次从堆顶取出最大的债权人和最大的债务人进行抵消剩余部分放回堆中继续。结果用上面的测试数据输出3笔。正确。4.3 第三轮边界条件验证我追加了几个边界测试案例1有人在账务中净额为0既不欠钱也不被欠预期不参与转账AI的代码不会加入堆中 → 正确案例2所有参与人都是债权人不可能因为总账必须平衡预期事务不一致抛出异常AI的代码如果堆为空 → 直接返回空列表 → 但账不平应该报错我补充了校验逻辑// 校验总账是否平衡doubletotal0;for(doublev:balance.values())totalv;if(Math.abs(total)0.001){thrownewIllegalStateException(账目不平衡请检查记录);}五、修正后的完整算法核心逻辑计算净额对每笔消费付款人加钱参与人减钱。分离债权人和债务人正余额为债权人应收负余额为债务人应付。贪心抵消用最大堆存储每次取最大债权人和最大债务人用较小的金额对冲。重复直到清零剩余部分放回堆中直到所有余额为0。为什么贪心是最优的每次消除当前最大的不平衡本质上是在每次迭代中最大程度地减少总转账次数。这个策略被称为“最小化转账次数的贪心算法”已经被证明在AA结算问题上是局部最优解且在实际场景中非常接近全局最优。完整代码publicclassAASettlement{publicstaticListTransfersettle(ListExpenseexpenses){// 1. 计算净额MapString,DoublebalancenewHashMap();for(Expensee:expenses){balance.put(e.payer,balance.getOrDefault(e.payer,0.0)e.amount);doublesharee.amount/e.participants.size();for(Stringp:e.participants){balance.put(p,balance.getOrDefault(p,0.0)-share);}}// 2. 校验总账doubletotal0;for(doublev:balance.values())totalv;if(Math.abs(total)0.001){thrownewIllegalStateException(账目不平衡);}// 3. 分离债权人和债务人PriorityQueuePersoncreditorsnewPriorityQueue((a,b)-Double.compare(b.balance,a.balance));PriorityQueuePersondebtorsnewPriorityQueue((a,b)-Double.compare(b.balance,a.balance));for(Map.EntryString,Doubleentry:balance.entrySet()){if(entry.getValue()0.001){creditors.offer(newPerson(entry.getKey(),entry.getValue()));}elseif(entry.getValue()-0.001){debtors.offer(newPerson(entry.getKey(),-entry.getValue()));}}// 4. 贪心抵消ListTransfertransfersnewArrayList();while(!creditors.isEmpty()!debtors.isEmpty()){Personccreditors.poll();Personddebtors.poll();doubleamountMath.min(c.balance,d.balance);transfers.add(newTransfer(d.name,c.name,amount));c.balance-amount;d.balance-amount;if(c.balance0.001)creditors.offer(c);if(d.balance0.001)debtors.offer(d);}returntransfers;}}六、给Vibe Coding开发者的实战建议1. 算法类需求给策略不给目标❌ 错误Prompt“帮我实现AA结算。”✅ 正确Prompt“用贪心算法实现AA结算每次取最大债权人和最大债务人抵消。”AI擅长实现“怎么做”不擅长思考“用什么方法做”。策略方向必须你来定。2. 提供反例是最好的“调优”方式我上面那个5人的测试数据是我手工推演出来的。把反例直接喂给AI比说“你的算法不够优”有效100倍。3. 边界条件要单独测试AI生成代码时往往只考虑正常情况边界条件如0余额、大额小数、多币种精度需要你单独写测试用例去验证。我的做法是先让AI生成代码然后我手写测试用例把测试结果再贴回给AI去修。4. 承认AI的局限性AI不是数学天才它不擅长“推理”出最优策略。它的强项是“理解策略并实现”。对于算法类需求你可以参考以下分工阶段谁来做原因选算法策略你自己AI不知道什么策略最优写实现代码AIAI擅长把策略转成代码提供反例你自己AI不知道自己的输出是不是最优修BugAI 你AI能修错但需要你指明方向边界测试你设计用例AI写测试分工协作效率最高七、最终成果经过三轮调优这个贪心算法已经在知途记账的旅行账本中正常运行。在真实使用场景中它的效果是一个5人7天的旅行约40笔消费结算时间100ms平均转账次数减少40%-60%相比直接两两结算支持均摊和自定义分摊比例支持多币种自动按记账时汇率换算你可以在这里体验https://ledger.dizena.com总结这次经历让我对Vibe Coding有了更深的理解AI写的代码能用但不一定最优。它的能力边界很清晰——能快速实现你描述的逻辑但不会“发现”更优的策略。所以我的工作流变成了我确定算法方向和策略人类负责“选方向”AI写初版代码AI负责“写代码”我手工推演找反例人类负责“找问题”AI修正AI负责“修Bug”我验证边界人类负责“把关”Vibe Coding不是“全自动编程”而是“人类定策略、AI写代码、人类验结果”的新协作模式。如果你也在用Vibe Coding写代码欢迎在评论区分享你的翻车经历——我保证你不是一个人。*本文首发于CSDN作者是位被AI算法坑过、但最终修好了的独立开发者。

相关新闻

Niva未来路线图:即将发布的5大功能与生态扩展计划

Niva未来路线图:即将发布的5大功能与生态扩展计划

Niva未来路线图:即将发布的5大功能与生态扩展计划 【免费下载链接】niva 一个基于 Tauri WRY 跨端 Webview 库的超轻量极易用的跨端应用开发框架。 项目地址: https://gitcode.com/gh_mirrors/ni/niva Niva作为基于Tauri WRY跨端Webview库的超轻量极易用的跨…

2026/7/22 23:32:25阅读更多 →
Velite核心功能揭秘:Markdown/MDX/YAML/JSON全支持

Velite核心功能揭秘:Markdown/MDX/YAML/JSON全支持

Velite核心功能揭秘:Markdown/MDX/YAML/JSON全支持 【免费下载链接】velite Turns Markdown / MDX, YAML, JSON, or others into apps data layer with Zod schema. 项目地址: https://gitcode.com/gh_mirrors/ve/velite Velite是一款强大的类型安全数据层构…

2026/7/22 23:32:25阅读更多 →
Ymir:让经典Sega Saturn游戏重获新生的终极模拟器完全指南

Ymir:让经典Sega Saturn游戏重获新生的终极模拟器完全指南

Ymir:让经典Sega Saturn游戏重获新生的终极模拟器完全指南 【免费下载链接】Ymir Sega Saturn emulator 项目地址: https://gitcode.com/gh_mirrors/ymir2/Ymir Ymir是一款功能强大的Sega Saturn模拟器,能够让玩家在现代设备上重温经典的Sega Sat…

2026/7/22 23:32:25阅读更多 →
深入解析MCU I/O引脚复用与Flash SECDED ECC机制:原理、配置与安全实践

深入解析MCU I/O引脚复用与Flash SECDED ECC机制:原理、配置与安全实践

1. 项目概述与核心价值在嵌入式微控制器(MCU)的世界里,尤其是面对汽车电子、工业控制这类对可靠性和资源利用率要求极高的领域,有两项底层技术是每一位资深工程师都必须吃透的:I/O引脚复用(Pin Multiplexin…

2026/7/23 0:26:35阅读更多 →
【Bug已解决】Support NexusQuant KV cache compression for memory reduction 解决方案

【Bug已解决】Support NexusQuant KV cache compression for memory reduction 解决方案

【Bug已解决】Support NexusQuant KV cache compression for memory reduction 解决方案 一、现象长什么样 在 DeepSpeed 做长上下文推理/训练时,KV cache(注意力键值缓存)是显存大户:序列越长、batch 越大,KV cache 占…

2026/7/23 0:24:35阅读更多 →
【Bug已解决】[REQUEST] Add Trackio as a New Backend for Experiment Monitoring 解决方案

【Bug已解决】[REQUEST] Add Trackio as a New Backend for Experiment Monitoring 解决方案

【Bug已解决】[REQUEST] Add Trackio as a New Backend for Experiment Monitoring 解决方案 一、现象长什么样 这是一个功能请求(feature request):用户希望 DeepSpeed 的实验监控(experiment monitoring)支持一个新的…

2026/7/23 0:24:35阅读更多 →
栈的应用(表达式求值)

栈的应用(表达式求值)

文章目录三种表达式的形式中缀表达式 转 后缀表达式手算方法机算中缀表达式 转 前缀表达式手算方法机算总结算数表达式由三部分组成:操作数、运算符、界限符(界限符是必不可少的,反映了计算的先后顺序)三种表达式的形式 首先要分…

2026/7/23 0:24:35阅读更多 →
开源大模型生态盘点:从Llama到Qwen的选型指南

开源大模型生态盘点:从Llama到Qwen的选型指南

打开 Hugging Face 的模型榜单,前排几乎每周都在换。Llama、Qwen、DeepSeek、Mistral、GLM……对想在自己的项目里跑一个开源模型的开发者来说,问题早已不是"有没有得选",而是"选错了要多花多少冤枉钱"。这篇文章按实际落…

2026/7/23 0:24:35阅读更多 →
AI媒体生产:从机器写作到智能编审流程

AI媒体生产:从机器写作到智能编审流程

媒体行业用机器写稿比大多数人想象得早。财经快讯里"某公司今日发布财报,营收同比增长 X%"这类句子,十年前就是模板生成的。变化发生在最近两三年:大模型让机器从"填数字"进化到"写整篇",同时把编审…

2026/7/23 0:24:35阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

2026/7/23 0:00:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/22 22:56:18阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/22 18:55:50阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/22 18:55:50阅读更多 →