1

I am trying to use substrings to calculate what the Roman numerals equal in arabic numbers, and I keep getting an index out of range error. Or, another way I had it, it would just read the second numeral and completely ignore the first.

System.out.println("What is the number you want converted?");
Scanner scan = new Scanner(System.in);
String Roman = scan.next();
int sum = 0;

for (int x = 0; x<Roman.length(); x++)
 {
  if (Roman.substring(x,(x+2)).equals("XC"))   
  {
    sum= sum+90;
  }    
  else if (Roman.substring(x,(x+1)).equals("IX"))
  {
    sum= sum+9;
  }   
  else if (Roman.substring(x).equals("X"))
  {
    sum= sum+10;
  }   
  else if (Roman.substring(x,(x+2)).equals("IV "))  
  {   
       sum= sum+4;
  }
    else if (Roman.substring(x).equals("V"))
  {
    sum= sum+5;
  } 
  else if (Roman.substring(x).equals("I"))
    {   
       sum= sum+1;
    }  
  else if (Roman.substring(x).equals("L"))
    {       
        sum= sum+50;
  }
  else if(Roman.substring(x).equals("C"))
  {
    sum= sum+100;
  }
} 
System.out.println(sum);
Erika
  • 31
  • 2
  • Could you provide the stacktrace of the exception (and tell us at which line in your code it failed)? Also, providing your input that causes the crash (here: number you want to convert) makes it a lot easier to debug ;) – Patrick Nov 28 '14 at 23:50
  • Hey, Erika. There are quite a few things wrong with your code, including some things that none of the answers here have identified yet. I would strongly recommend that you step through this with a debugger - see what's happening to `x` as the program progresses, and you'll see immediately why that exception's being thrown. Also, one more hint (but not related to the exception) - when you use `substring` and only supply a single argument; you don't get just one character, you get everything from the position you specify up till the end of the `String`. – Dawood ibn Kareem Nov 29 '14 at 02:48

3 Answers3

0

There are two problems with the code:

  1. you are doing x+2 or x+1 even if you are at the end of the string. This is causing the exception. Make sure you are only looking for XC of XI when there is still more than one charater left.

  2. When you read a character which is more that one sign you don't advance you're pointer with the lenght of the sign you're reading. This way you read the same character twice. So if you read XC you should increment x one more time.

Kevin Kopf
  • 13,327
  • 14
  • 49
  • 66
0

You've a couple problems:

  1. When matching 2-character substrings, you are going off the end of the string.
  2. You are matching two characters at a time while only looping singly.

The first one is causing your problem.

A quick and dirty way to fix it is to add if (Roman.length()>= x+2 && to each of the two-character substrings, and also add an x++ in the code block against it. I.e.:

else if (Roman.length() >= x+2 && Roman.substring(x,(x+2)).equals("IV "))  
{   
     sum= sum+4;
     x++;
}

This is super hacky, there are certainly better way to go about this.

Allen Luce
  • 7,859
  • 3
  • 40
  • 53
0

Coincidentally I told a friend about this problem this evening and he came up with this rather compact solution. Two numbers next to each other are compared and depending on whether the next number is bigger or less than the number before it, it is subtracted or added. I've added his solution down here, maybe it can help you. There are also some other nice solutions to this problem on Stackoverflow. See: Converting Roman Numerals To Decimal.

import acm.program.*;

public class RomanNumeralsToArabic extends ConsoleProgram {

public void run() {

    /* Read in the roman numeral from the user and store it as a String. */ 
    String romanNumber = readLine("Enter roman number: ");

    /* Initialize the array to store the arabic equivalents of the roman numerals in. */
    int[] arabicArray = new int[romanNumber.length()];

    /* Loop through the charachters of the roman number and store the arabic equivalents in the array. */
    for (int i = 0; i < romanNumber.length(); i++) {
        char ch = romanNumber.charAt(i);
        switch (ch) {
            case 'M': arabicArray[i] = 1000; break;
            case 'D': arabicArray[i] = 500; break;
            case 'C': arabicArray[i] = 100; break;
            case 'L': arabicArray[i] = 50; break;
            case 'X': arabicArray[i] = 10; break;
            case 'V': arabicArray[i] = 5; break;
            case 'I': arabicArray[i] = 1; break;
        }
    }

    /* The last roman numeral is always added to the total no matter what it is. */
    int result = arabicArray[arabicArray.length - 1];

    /* Loop through the array with arabic numbers. If the number in the next bucket is
     * less than the one before it, subtract the number. If it is bigger, add it. */
    for (int j = 0; j < arabicArray.length - 1; j++) {
        if (arabicArray[j] >= arabicArray[j + 1]) {
            result += arabicArray[j];
        } else {
            result -= arabicArray[j];
        }
    }

    /* Print out the result to the screen. */
    println("Arabic number: " + result);

}

}

Community
  • 1
  • 1
Parsijn
  • 31
  • 4