Java罗马数字转整数无限循环问题求解(未学数组/Map)
罗马数字转整数无限循环问题解决
问题背景
我是Java新手,还没学数组和映射,要写整数与罗马数字互转程序。整数转罗马数字功能正常,但罗马数字转整数时出现无限循环,不知道原因。需要修改while循环终止无限循环。
规则说明:无需考虑IV这类特殊写法,4用IIII表示,9用VIIII表示,仅使用M、D、C、L、X、V、I字符。需实现三个构造函数:无参、接收字符串、接收整数的构造函数。
我的RomanNumeral类代码:
package jfauvelle_G10_A04; public class RomanNumeral { private String romanNum = ""; private int decimalNum = 0; public RomanNumeral() { romanNum = ""; decimalNum = 0; } public RomanNumeral(String r) { decimalNum = convertRomanToInteger(r); romanNum = r; } public RomanNumeral(int i) { romanNum = convertIntegerToRoman(i); decimalNum = i; } public void setRomanNumeral(String r) { romanNum = r; } public String getRomanNumeral() { return romanNum; } public void setDecimalNumeral(int i) { decimalNum = i; } public int getDecimalNumeral() { return decimalNum; } public String convertIntegerToRoman(int r) { int roman = r; String finalRoman = ""; while (roman >= 1000) { finalRoman = finalRoman + "M"; roman -= 1000; } while (roman >= 500) { finalRoman = finalRoman + "D"; roman -= 500; } while (roman >= 100) { finalRoman = finalRoman + "C"; roman -= 100; } while (roman >= 50) { finalRoman = finalRoman + "L"; roman -= 50; } while (roman >= 10) { finalRoman = finalRoman + "X"; roman -= 10; } while (roman >= 5) { finalRoman = finalRoman + "V"; roman -= 5; } while (roman >= 1) { finalRoman = finalRoman + "I"; roman -= 1; } return finalRoman; } private int convertRomanToInteger(String n) { String decimal = n; int finalDecimal = 0; for (int i = 0; i <= decimal.length(); i++) { while (decimal.charAt(i) == 'M') { finalDecimal += 1000; } while (decimal.charAt(i) == 'D') { finalDecimal += 500; } while (decimal.charAt(i) == 'C') { finalDecimal += 100; } while (decimal.charAt(i) == 'L') { finalDecimal += 50; } while (decimal.charAt(i) == 'X') { finalDecimal += 10; } while (decimal.charAt(i) == 'V') { finalDecimal += 5; } while (decimal.charAt(i) == 'I') { finalDecimal += 1; } } return finalDecimal; } }
主类代码:
public class RomanNumeralCalculatorTestCase { public static void main(String[] args) { boolean working = true; RomanNumeral case1 = new RomanNumeral(); case1.setRomanNumeral("XVI"); if (case1.getRomanNumeral() != "XVI") { working = false; System.err.println("ERROR: Roman numeral was not set properly. It is " + case1.getRomanNumeral() + ". It should be XVI"); } case1.setDecimalNumeral(2004); if (case1.getDecimalNumeral() != 2004) { working = false; System.err.println("ERROR: Decimal number was not set properly. It is " + case1.getDecimalNumeral() + ". It should be XVI"); } RomanNumeral case2 = new RomanNumeral(1000); String s = "M"; if(!(case2.getRomanNumeral().equals(s))) { working = false; System.err.println("ERROR: Decimal number was not set properly. It is " + case2.getRomanNumeral() + ", it should be M."); } RomanNumeral case3 = new RomanNumeral("M"); if(case3.getDecimalNumeral() != 1000) { working = false; System.err.println("ERROR: Decimal number was not set properly. It is " + case3.getDecimalNumeral() + ". It should be 1000"); } if(working) System.out.print("Congratz ! The test case work !"); } }
我曾尝试使用简单数组但未成功,若有易懂的数组方案,我也乐意接受,希望能理解解决方案。
无限循环原因分析
- while循环无终止条件:
convertRomanToInteger方法里,每个while循环的条件永远不会改变——比如遇到'M'时,while (decimal.charAt(i) == 'M')会一直为true,因为你既没有移动索引i,也没有修改字符串,导致循环永远无法退出,直接触发无限循环。 - 数组越界风险:外层
for循环的条件是i <= decimal.length(),但字符串的索引范围是0到length-1,当i等于length时,decimal.charAt(i)会抛出StringIndexOutOfBoundsException异常。
解决方案
方案一:不用数组,替换while为if
外层for循环已经在逐个遍历每个字符,每个位置只需要判断一次对应数值并累加,完全不需要while循环。修改后的convertRomanToInteger方法:
private int convertRomanToInteger(String n) { int finalDecimal = 0; // 修正循环条件,避免越界 for (int i = 0; i < n.length(); i++) { char currentChar = n.charAt(i); if (currentChar == 'M') { finalDecimal += 1000; } else if (currentChar == 'D') { finalDecimal += 500; } else if (currentChar == 'C') { finalDecimal += 100; } else if (currentChar == 'L') { finalDecimal += 50; } else if (currentChar == 'X') { finalDecimal += 10; } else if (currentChar == 'V') { finalDecimal += 5; } else if (currentChar == 'I') { finalDecimal += 1; } } return finalDecimal; }
方案二:易懂的数组方案
用两个平行数组分别存储罗马字符和对应数值,遍历数组匹配字符,代码更简洁:
private int convertRomanToInteger(String n) { int finalDecimal = 0; // 罗马字符与对应数值一一对应 char[] romanChars = {'M', 'D', 'C', 'L', 'X', 'V', 'I'}; int[] values = {1000, 500, 100, 50, 10, 5, 1}; for (int i = 0; i < n.length(); i++) { char current = n.charAt(i); // 遍历数组找到当前字符对应的数值 for (int j = 0; j < romanChars.length; j++) { if (current == romanChars[j]) { finalDecimal += values[j]; break; // 找到后立即退出内层循环,提升效率 } } } return finalDecimal; }
测试代码修正
测试代码里有两个小问题需要修正:
- 字符串相等判断要用
equals()方法,不能用!=,否则会比较对象地址而非内容:
// 原代码 if (case1.getRomanNumeral() != "XVI") { // 修改为 if (!case1.getRomanNumeral().equals("XVI")) {
case1的错误提示里,把目标数值"2004"写成了"XVI",修正为:
System.err.println("ERROR: Decimal number was not set properly. It is " + case1.getDecimalNumeral() + ". It should be 2004");
内容的提问来源于stack exchange,提问作者Skyzreal
相关产品推荐
相关产品推荐

