You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 !");
    }
}

我曾尝试使用简单数组但未成功,若有易懂的数组方案,我也乐意接受,希望能理解解决方案。


无限循环原因分析

  1. while循环无终止条件:convertRomanToInteger方法里,每个while循环的条件永远不会改变——比如遇到'M'时,while (decimal.charAt(i) == 'M')会一直为true,因为你既没有移动索引i,也没有修改字符串,导致循环永远无法退出,直接触发无限循环。
  2. 数组越界风险:外层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;
}

测试代码修正

测试代码里有两个小问题需要修正:

  1. 字符串相等判断要用equals()方法,不能用!=,否则会比较对象地址而非内容:
// 原代码
if (case1.getRomanNumeral() != "XVI") {
// 修改为
if (!case1.getRomanNumeral().equals("XVI")) {
  1. case1的错误提示里,把目标数值"2004"写成了"XVI",修正为:
System.err.println("ERROR: Decimal number was not set properly. It is " + case1.getDecimalNumeral()
        + ". It should be 2004");

内容的提问来源于stack exchange,提问作者Skyzreal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:56:29