程序员可以放心了,ChatGPT只能写95的代码!
领域特定语言 (DSL)可能很多人都知道,就是针对特定领域的,一个简单的"小语言",例如HTML就是针对Web编程的一个DSL,SQL是针对数据库操作的一个DSL。
DSL可以很复杂,也包含if, else,while等逻辑控制,也可以很简单,我选这个例子就是 税务领域 的一个简单例子: // 定义税率区间 tax_bracket 1 range: 0 - 15000 rate: 5% tax_bracket 2 range: 15001 - 45000 rate: 10% tax_bracket 3 range: 45001 - 120000 rate: 20% tax_bracket 4 range: 120001 - 200000 rate: 30% tax_bracket 5 //注:就是这个不同寻常的格式引发了Bug range: 200001 and above rate: 40% // 定义抵免额 deduction Standard amount: 5000 deduction Health_Insurance amount: 2000 deduction Retirement_Savings amount: 3000
有了这些术语,业务人员就可以使用了 // 计算应纳税额 income: 80000 deductions: Standard, Health_Insurance, Retirement_Savings calculate_tax
我把这个需求直接抛给GPT-4, 让它用Java语言给我实现了,下面是我和它的对话:
注:交互内容较长,文末有总结
GPT-4 :为了实现这个DSL,我将首先创建一个TaxBracket类来表示税率区间,然后创建一个Deduction类来表示抵免额。最后,我将创建一个TaxCalculator类来实现计算应纳税额的逻辑。以下是一个简化的Java实现: import java.util.ArrayList; import java.util.Arrays; import java.util.List; class TaxBracket { int id; int lowerBound; int upperBound; double rate; public TaxBracket(int id, int lowerBound, int upperBound, double rate) { this.id = id; this.lowerBound = lowerBound; this.upperBound = upperBound; this.rate = rate; } } class Deduction { String name; int amount; public Deduction(String name, int amount) { this.name = name; this.amount = amount; } } class TaxCalculator { List taxBrackets; List deductions; int income; public TaxCalculator(int income, List taxBrackets, List deductions) { this.income = income; this.taxBrackets = taxBrackets; this.deductions = deductions; } public double calculateTax() { int taxableIncome = income; for (Deduction deduction : deductions) { taxableIncome -= deduction.amount; } double tax = 0; for (TaxBracket bracket : taxBrackets) { if (taxableIncome <= bracket.upperBound) { tax += (taxableIncome - bracket.lowerBound ) * bracket.rate; break; } else { tax += (bracket.upperBound - bracket.lowerBound ) * bracket.rate; } } return tax; } } public class Main { public static void main(String[] args) { List taxBrackets = new ArrayList<>(Arrays.asList( new TaxBracket(1, 0, 15000, 0.05), new TaxBracket(2, 15001, 45000, 0.10), new TaxBracket(3, 45001, 120000, 0.20), new TaxBracket(4, 120001, 200000, 0.30), new TaxBracket(5, 200001, Integer.MAX_VALUE, 0.40) )); List deductions = new ArrayList<>(Arrays.asList( new Deduction("Standard", 5000), new Deduction("Health_Insurance", 2000), new Deduction("Retirement_Savings", 3000) )); int income = 80000; TaxCalculator calculator = new TaxCalculator(income, taxBrackets, deductions); double tax = calculator.calculateTax(); System.out.println("应纳税额: " + tax); } }
这个实现定义了TaxBracket和Deduction类,并创建了一个TaxCalculator类来计算应纳税额。主方法中初始化了税率区间和抵免额,并使用这些信息计算了一个给定收入的应纳税额。
注:它似乎理解了这个DSL是用来计算税率的,类名,方法名也比较合理
刘欣 :不不不,应该解析一个DSL文件,形成TaxBracket和Deduction,然后再计算税率, 你这里少了一个解析器
GPT-4 :抱歉,我明白你的需求了。这里是一个使用Java编写的解析器,用于解析DSL文件并计算税率:
首先,我们需要创建一个名为 DSLParser 的类来解析DSL文件: import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; class DSLParser { private final List taxBrackets = new ArrayList<>(); private final List deductions = new ArrayList<>(); private int income; public DSLParser(String filePath) { try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { String line; while ((line = reader.readLine()) != null) { parseLine(line.trim()); } } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } } private void parseLine(String line) { if (line.startsWith("tax_bracket")) { int id = Integer.parseInt(line.split(" ")[1]); int lowerBound = 0; int upperBound = 0; double rate = 0; for (int i = 0; i < 2; i++) { line = getNextLine(); if (line.startsWith("range:")) { String[] range = line.substring(6).trim().split(" - "); lowerBound = Integer.parseInt(range[0]); if (range[1].equals("and above")) { upperBound = Integer.MAX_VALUE; } else { upperBound = Integer.parseInt(range[1]); } } else if (line.startsWith("rate:")) { rate = Double.parseDouble(line.substring(5).trim().replace("%", "")) / 100; } } taxBrackets.add(new TaxBracket(id, lowerBound, upperBound, rate)); } else if (line.startsWith("deduction")) { String name = line.split(" ")[1]; int amount = 0; line = getNextLine(); if (line.startsWith("amount:")) { amount = Integer.parseInt(line.substring(7).trim()); } deductions.add(new Deduction(name, amount)); } else if (line.startsWith("income:")) { income = Integer.parseInt(line.substring(7).trim()); } else if (line.equals("calculate_tax")) { // Do nothing, just a marker to calculate tax } } private String getNextLine() { // Read the next line from the file, or return null if end of file is reached } public List getTaxBrackets() { return taxBrackets; } public List getDeductions() { return deductions; } public int getIncome() { return income; } }
接下来,我们需要修改Main类,以便从DSL文件读取税收信息并计算税率: public class Main { public static void main(String[] args) { if (args.length != 1) { System.out.println("Usage: java Main "); return; } DSLParser parser = new DSLParser(args[0]); List taxBrackets = parser.getTaxBrackets(); List deductions = parser.getDeductions(); int income = parser.getIncome(); TaxCalculator calculator = new TaxCalculator(income, taxBrackets, deductions); double tax = calculator.calculateTax(); System.out.println("应纳
注:这里没输出完,就断掉了。
刘欣:继续
GPT-4 : 税额: " + tax); } }
现在,这个实现已经包括了解析DSL文件的功能。你可以将上述代码保存为Java源文件(例如`TaxCalculation.java`),并将你的DSL文件保存为一个文本文件(例如`tax.dsl`)。然后使用以下命令编译并运行代码: javac TaxCalculation.java java Main tax.dsl
这将从 tax.dsl文件读取税率区间和抵免额信息,并根据收入计算税率。请注意,在使用此方法之前,你可能需要稍微调整DSLParser类中的getNextLine方法,以便正确读取文件的下一行。你可以使用BufferedReader对象的readLine方法实现这一点。
刘欣: DSLParser中getNextLine方法没有实现!
GPT-4 :抱歉,这是我的疏忽。请在DSLParser类中添加一个BufferedReader类型的成员变量reader,并在构造函数中初始化它。然后在getNextLine方法中实现读取下一行的逻辑。以下是修改后的DSLParser类: class DSLParser { private final List taxBrackets = new ArrayList<>(); private final List deductions = new ArrayList<>(); private int income; private BufferedReader reader; public DSLParser(String filePath) { try { this.reader = new BufferedReader(new FileReader(filePath)); String line; while ((line = reader.readLine()) != null) { parseLine(line.trim()); } reader.close(); } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } } private void parseLine(String line) { // ... (same as before) } private String getNextLine() { try { return reader.readLine(); } catch (IOException e) { System.err.println("Error reading next line: " + e.getMessage()); return null; } } // ... (getTaxBrackets, getDeductions, and getIncome methods) }
现在,DSLParser类已包含一个reader成员变量,用于在getNextLine方法中读取文件的下一行。这应该使解析器能够正确解析DSL文件并计算税率。
注: 到目前为止,GPT-4把所有的代码都生成了,用时不到5分钟!可以说是神速了,让我从头开始构思,然后一行行敲出代码,恐怕得四五十分钟吧
我把它复制出来,在VS Code中运行,发现了一个问题, 它没有处理文本前后的空格。
刘欣:在parseLine方法中,你好像没有考虑文件中的一行内容前后有空格的问题
GPT-4 :您是对的,我之前的实现没有考虑到行内容前后可能存在的空格。在解析每一行时,我们可以使用trim()方法来去除前后的空格。以下是修改后的DSLParser类中的parseLine方法: private void parseLine(String line) { line = line.trim(); if (line.startsWith("tax_bracket")) { // ... (same as before) } else if (line.startsWith("deduction")) { // ... (same as before) } else if (line.startsWith("income:")) { income = Integer.parseInt(line.substring(7).trim()); } else if (line.equals("calculate_tax")) { // Do nothing, just a marker to calculate tax } }
现在,我们在处理每一行时都会去掉前后的空格,这样就可以更准确地解析含有前后空格的行内容。这将提高解析器的健壮性,使其能够更好地处理不同格式的DSL文件。
注:其实GPT-4只改了一处代码,其他地方还没改。于是我建议它:
刘欣:能否在getNextLine方法中就做trim呢?
GPT-4 : 当然可以。您可以在getNextLine方法中直接对读取到的行内容进行trim()操作。这样,在调用getNextLine方法时,就可以确保返回的行内容已经去除了前后的空格。以下是修改后的getNextLine方法: private String getNextLine() { try { String line = reader.readLine(); if (line != null) { return line.trim(); } } catch (IOException e) { System.err.println("Error reading next line: " + e.getMessage()); } return null; }
在这个修改后的版本中,我们在getNextLine方法内部对读取到的行内容使用了trim()方法。这意味着在解析文件时,无论是通过getNextLine方法还是在parseLine方法中读取的行内容,都已经去除了前后的空格。
注:到目前为止,还一切顺利,但是很快就发生了一件让人头大的问题:GPT-4在处理range: 200001 and above 这样格式的时候出错, 因为一般的格式是45001 - 120000, 120001 - 200000 ,都是数字,这里出现一个 and above 文字,它没注意到。
程序在运行时出错,我把错误直接扔给它:
刘欣:代码在运行时出错: Exception in thread "main" java.lang.NumberFormatException: For input string: "200001 and above" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at DSLParser.parseLine(App.java:94) at DSLParser.(App.java:73) at App.main(App.java:150)
GPT- 4 :抱歉给您带来了困扰。这个问题是由于在解析tax_bracket区间的上界时没有正确处理"and above"的情况导致的。以下是修复后的parseLine方法中处理tax_bracket部分的代码:代码略。
注:GPT-4虽然意识到了问题所在,但是它的修改方案总是有问题,反复了两三次也修不好。最后我提示它:
刘欣:在这个字符串中 range: 200001 and above , 根据就没有"-", 所以line.substring(6).trim().split(" - ") 这行代码是没用的
GPT-4: 您是对的,我再次犯了错误。为了处理"and above"这种情况,我们应该根据"and above"字符串来分割范围。以下是修复后的parseLine方法中处理tax_bracket部分的代码: private void parseLine(String line) { if (line.startsWith("tax_bracket")) { int id = Integer.parseInt(line.split(" ")[1]); int lowerBound = 0; int upperBound = 0; double rate = 0; for (int i = 0; i < 2; i++) { line = getNextLine(); if (line.startsWith("range:")) { String rangeString = line.substring(6).trim(); if (rangeString.contains("and above")) { String[] range = rangeString.split(" and above"); lowerBound = Integer.parseInt(range[0]); upperBound = Integer.MAX_VALUE; } else { String[] range = rangeString.split(" - "); lowerBound = Integer.parseInt(range[0]); upperBound = Integer.parseInt(range[1]); } } else if (line.startsWith("rate:")) { rate = Double.parseDouble(line.substring(5).trim().replace("%", "")) / 100; } } taxBrackets.add(new TaxBracket(id, lowerBound, upperBound, rate)); } else if (line.startsWith("deduction")) { // ... (same as before) } else if (line.startsWith("income:")) { income = Integer.parseInt(line.substring(7).trim()); } else if (line.equals("calculate_tax")) { // Do nothing, just a marker to calculate tax } }
现在,在解析税率区间时,我们首先检查范围字符串是否包含"and above"。如果包含,则根据"and above"分割范围,并将上界设置为Integer.MAX_VALUE。否则,我们使用" - "分隔符来分割范围。这次修改应该可以正确处理税率区间,并避免NumberFormatException异常。
注:这一次,它终于做对了。
总结一下:
ChatGPT实在是太牛了!
它不但可以理解需求,生成代码, 更让人震撼的是可以根据要求不断地微调代码,完善功能,修复Bug 。
过程完全用自然语言交互,这种能力我没有在之前的任何工具中看到过,说它是革命性的技术完全不为过。
但是,我们也看到了它忘记(?)实现一个方法,特别是一个Bug一直搞不定,直到我明确地指出来。
正如球友@楊_宵夜所说: ChatGPT能以极快的速度生成95%的可运行代码,但是剩下的5%依然依靠程序员的功力。
在ChatGPT的冲击下,程序员的价值依然是很大的,依然是不可或缺的的 。
但是,会用熟练使用ChatGPT的程序员,可以用自然语言快速生成代码,效率提升十倍甚至百倍,这将 对不使用ChatGPT的程序员构成降维打击 。
性启蒙教育(雁霞)现在网络这么发达,许多知识都可以从网上学到,关于性的问题,父母多不会细致地传授经验,平时鲜有提及。今年春季教学六年级科学时,学到了精子和卵子结合成受精卵,就在女性的子宫里面发育成胎
孕期出现的8种问题,该怎么应对呢?我今天353周啦,给大家分享一下整个孕期会出现哪些症状,针对这些症状孕妈妈们又该怎么应对呢?1孕吐应该少食多餐,喝柠檬水苏打水,并且遵循医嘱来服用维生素B6等药物,以得到缓解2嗜睡
难怪你冲的藕粉不透明,原来是水温不对,掌握这个标准,一次成功大家好!欢迎来到喷香小厨。今天给大家分享的题目是难怪你冲的藕粉不透明,原来是水温不对,掌握这个标准,一次成功。去年因为胃不舒服,去医院做了胃镜检查,结果有些胃粘膜糜烂。除了吃药,医
哪个牌子的饼干比较好吃,经测评,这4款榜上有名,看看你吃过吗哪个牌子的饼干比较好吃,经测评,这4款榜上有名,看看你吃过吗饼干大家都吃过吧,它既能当做零食,有时候还能当做饭,日常来不及吃饭了,就会选择用饼干进行饱腹,当早餐加餐或是煎点,饱腹感
面条哪的好吃?经评选,全国这6大面条榜上有名,看有你家乡的没大家好,我是大雄。你知道全国排名前6的面条是哪些吗?你知道你们家乡的特色面食是什么吗?你有吃过吗?今天就来给大家唠一唠,这些比较出名的面条究竟是什么,它们的特色又是什么,为什么会赢
事关房屋租金减免!国资委发文国资委进一步做好2022年服务业小微企业和个体工商户房屋租金减免工作国务院国资委日前发出关于进一步做好2022年服务业小微企业和个体工商户房屋租金减免工作的通知,要求各中央企业和地
喜迎二十大转型再出发资源型地区转型发展工作纪实之六山东省淄博市博山独立工矿区编者按资源型地区是我国重要的能源资源保障基地,为支撑国家经济社会发展作出了重要贡献。在长期的资源开采过程中,也形成了一批采煤沉陷区独立工矿区等困难地区。党的十八大以来,我委会同有关
9月SUV销量出炉,断层明显!非豪华燃油SUV压力山大作为在中国市场最吃香的车型,SUV的发展史同样也是过去几年中国车市的发展史。前几年,依靠着SUV,许多车企在销量以及市场认可度上取得了不俗的成绩,但如今随着新能源浪潮的到来,SUV
蒙牛狂奔8亿再出手,卢敏放加速并购文丨吴大郎出品丨牛刀财经(niudaocaijing)蒙牛创始人牛根生曾提出过一个飞船定律,蒙牛不是在高速中成长,就是在高速中毁灭。如果达不到环绕速度,那么只能掉下来。5年前开始的
正式确定!宁德上榜近日,工业和信息化部正式确定杭州武汉成都宁德南通潍坊合肥株洲广州深圳包头齐齐哈尔等12个城市首批开展产业链供应链生态体系建设试点。宁德锂电新能源小镇。多上几个大项目,多抱几个金娃娃
北溪管道爆炸,全球抢购中国船,背后的真相到底是什么?作者李云飞来源原创一位久经商场的创业老司机,关注我,每天分享一点财富干货,让你的人生少走弯路。北溪管道被炸,全球开始疯狂抢购中国船,中国船企订单甚至排到了2026年。这真的是有心栽
五个长寿习惯,一定要知道今天推荐著名杂志柳叶刀发布的5个长寿习惯,普通人要想健康长寿,一定要知道并遵循!这个五个习惯做到的人,男性可以平均延长8。8年,女性可以延长8。1年。第一,不吸烟或者尽早戒烟第二,
百姓说变化黄江黄牛埔村客家文化获新生,村子焕发新活力我在黄牛埔住了差不多23年,近几年黄牛埔的发展速度特别快,尤其是广场和两边的牌楼建起来,小朋友们周末或者是放假的时候都有可去之处,老人家们平时也经常聚集在长廊聊天休息。市民胡女士说
(经济)我国首次散船进口巴西玉米1月7日,一艘载有巴西玉米的货轮自巴西桑托斯港抵达广东麻涌港。船上由中粮集团进口的6。8万吨巴西玉米完成检验检疫后,将快速送达国内饲料企业手中。据介绍,这是我国首次散船进口巴西玉米
路边的玉米糁子早晨步行去铁路大厂临时上班几天,路过槐荫街,忽然看到路边有些金黄色的玉米糁子散落在墙根下。我就琢磨着,这肯定是好心人怕鸟雀们天冷无处觅食饿死而故意撒下的。就像大山里秋天有些树上的柿
联合国粮农组织2022年世界玉米和小麦价格均创历史新高来源中国新闻网中新社北京1月6日电联合国粮农组织(下称粮农组织)6日披露的数据显示,2022年12月国际食品价格指数连续第九个月下降。但纵观2022年全年,国际食品价格指数同比仍大
村里生活喜欢这简简单单的乡村生活喜欢晚饭过后的篝火喜欢听爷爷奶奶的爱情故事静谧而美好爷爷奶奶携手走过五十年的时光吵过闹过,现在看着爷爷奶奶斗嘴的画面,大抵也是那个年代美好的见证每每坐着聊天
探寻京城烟火,这些京味十足北京胡同一定不要错过!北京胡同,最接地气的人间烟火胡同,是北京的文化特色,也是老北京城的根,想要了解这座历史悠久的京城,就从北京胡同开始。北京城里独有的烟火,就藏在这些胡同里,最低调的京味胡同,每一条胡
文山这个村子变成了景区!你不去看看?青瓦白墙一栋栋房屋错落有致红色徽标点缀其中门前的红旗迎风飘扬院中的小景各有千秋改造后的洒戛竜村将红色革命精神展现得淋漓尽致徽标点缀白墙风景别具一格洒戛竜是文山地区傣族(当地称为摆依
豆粕将高位下行,玉米价格坚挺,2023年饲料行业景气回暖利于行业巨头界面预言家过去几年,饲料行业集中度逐步提升。目前饲料行业适逢两年的机遇窗口期,2022年的竞争形势可以总结为小型企业退出,中型企业无竞争力,大企业陷入养猪不能自拔,有些大企业进入老年期。饲料
小山村里的幸福苑宜居宜业和美乡村正当时来源人民网安徽频道晨昏渺渺,河水清浅,拥山而眠。大片的绿在视野间无限拉长,竹海翻涌,凌冽的竹香萦绕鼻尖,依稀带着露水的清冷。凝望这片土地,柏油路毛竹林篱笆墙柿子树清水塘桥下洞天空湛
11战8负!冠军教头把CBA冲冠队带进死胡同,离下课不远了?CBA第二十一轮比赛,爆出本赛季最大冷门,黑马山西队出人意料地输给了一场未胜的超级鱼腩宁波队,在网上引起热议,成为CBA的头条新闻。山西队也是有一定底蕴的球队,多年前曾经在季后赛打