Project Euler第17题:修改Java代码后结果偏差巨大的问题排查
Project Euler 第17题问题排查与优化建议
问题背景
我正在解决Project Euler第17题,需求是编写程序统计1-1000的英文拼写总字符数(忽略空格和连字符,百位表述需包含'and')。初始代码大部分正常,但整百数会多统计一个'and'(比如把600算成'six hundred and'),导致结果比预期值21124多27。修改循环中的两行代码后,输出结果变为18487,偏差极大,希望了解原因,同时寻求代码优化建议,不想直接通过sum-27来凑正确结果。
代码片段
初始代码片段
num += i > 99 ? "hundredand".length() : 0; num += ones.get(i / 100);
修改后的代码片段
num += i>99 ? "hundred".length() : 0; num += i%100==0 ? 3 : 0;
修改后代码的问题分析
- 逻辑完全倒置:题目要求非整百的三位数才需要加"and"(比如101是"one hundred and one"),整百数不需要(比如600是"six hundred")。但修改后的代码是给整百数加3("and"的长度),非整百的三位数反而不加,完全搞反了规则。
- 计算偏差来源:初始代码的问题是所有三位数都加了"hundredand"(长度10),9个整百数每个多算3字符,总共多27。修改后,整百数还是加了7+3=10(和初始一样错),但非整百的891个三位数每个少算3字符,891*3=2673,21124+27-2673=18478,和你得到的18487接近,核心是逻辑错误导致的大规模少算。
正确的代码修正方案
核心是区分整百和非整百的三位数:
// 替换原来的两行代码 if (i > 99) { // 先加百位数字的单词长度(比如six对应3) num += ones.get(i / 100); // 根据是否为整百数,加对应的单位长度 if (i % 100 == 0) { num += "hundred".length(); // 整百数,仅加hundred的长度7 } else { num += "hundredand".length(); // 非整百,加hundred+and的长度10 } }
或者用三元表达式简化写法(可读性稍弱):
num += ones.get(i / 100); num += i > 99 ? (i % 100 == 0 ? "hundred".length() : "hundredand".length()) : 0;
代码优化建议
- 预存所有单词长度:把0-19、20/30.../90、"hundred"、"hundredand"、"onethousand"的长度提前存入数组或Map,避免重复计算字符串长度,提升效率。
- 分阶段处理数字:
- 0-19:直接取预存长度;
- 20-99:十位长度 + (个位非0则加个位长度);
- 100-999:百位长度 + (整百则hundred,非整百则hundredand) + (后两位非0则加后两位长度);
- 单独处理1000:直接加"onethousand"的长度11。
- 简化分支逻辑:避免嵌套过深的三元表达式,用清晰的if-else提升代码可读性,方便后续维护和排查问题。
内容的提问来源于stack exchange,提问作者user23157819
相关产品推荐
相关产品推荐

