Java Tutorial
YearToRomanNumerals Problem

Before you start coding you need to know what you're trying to accomplish. What is the program supposed to do? In the YearToRomanNumerals problem - we basically want to take a year and convert it into it's Roman Numeral equivalent. That sounds easy enough. But what does it take to actually get the computer to do it?

Let's first review some numbers and their Roman Numerals.

1=I
2=II
3=III
4=IV
5=V
6=VI
7=VII
8=VIII
9=IX
10=X

11=XI
12=XII
13=XIII
14=XIV
15=XV
16=XVI
17=XVII
18=XVIII
19=XIX
20=XX

30=XXX
40=XD
50=D
60=DX
70=DXX
80=DXXX
90=XC
100=C
500=L
1000=M


You should notice a pattern in the above chart. Notice that it's only made up of 7 unique letters and by adding and subtracting you can create at least 3,999 numbers. Let's take a simple number that's not on the chart - 800. Looking at the chart you should be able to figure out that 800=LCCC or 500+100+100+100.

Now let's take 1987. When we convert 1987 we get MCMDXXXVII. The easiest way of making the convertion is to break the number apart. In other words - it becomes 1000+900+80+7 or M +CM + DXXX + VII.

Looking at this, we now see that we should have four methods - getThousands(), getHundreds(), getTens(), getOnes(). These methods will actually perform the conversion and return back the corresponding Roman Numeral.

We need a way to obtain the year some how. For our purposes - we'll just have the user include it on the command line when they run the program. So in order to successfully run the program, they would enter - ..\bin\java YearToRomanNumerals 1987.

Although we could include all the method calls from the main method - similar to what we did in SmartHello, that's not good programming style. The main method should have very little in it. So let's have a method that is called from main, then this new method can call getThousands(), getHundreds(), etc. We'll call this new method convertYear().

Now let's convert what we've got so far into some pseudo-code. Pseudo-code is a shorthand for describing the solution without being as specific as the actual code has to be.

main(year)
  convertYear()

convertYear()
  getThousands()
  getHundreds()
  getTens()
  getOnes()
  Printout year in roman numerals.

getThousands()
  if thousands=1 then return "M"
  if thousands=2 then return "MM"
  if thousands=3 then return "MMM"

getHundreds()
  if hundreds=1 then return "C"
  if hundreds=2 then return "CC"
  if hundreds=3 then return "CCC"
  if hundreds=4 then return "CL"
  if hundreds=5 then return "L"
  if hundreds=6 then return "LC"
  •
  •
  if hundreds=9 then return "CM"

getTens()
  if tens=1 then return "X"
  if tens=2 then return "XX"
  •
  •
  if tens=5 then return "L"
  if tens=6 then return "LX"
  •
  •
  if tens=9 then return "XC"

getOnes()
  if ones=1 then return "I"
  if ones=2 then return "II"
  •
  •
  if ones=5 then return "V"
  if ones=6 then return "VI"
  •
  •
  if ones=9 then return "IX"

Now that we have an idea of how the program will work - let's start fleshing it out with some code. We know we need the public class and the main method. so let's get those down now. Also remember that we need to create an object from our public class - which we'll call YearToRomanNumerals.

public class YearToRomanNumerals
{  public state void main(String[] args)
   { YearToRomanNumerals yearToRomanNumerals= new YearToRomanNumerals();

Notice that YearToRomanNumerals is the class name and yearToRomanNumerals is the object name.

Now what? How do we get the year that the user inputs on the command line. That's where the String[] args comes in. The brackets indicate that the variable args is an array of Strings.

What is an array? Think of an array as a variable that is capable of holding multiple values that are accessed by using an index. We will be going into detail on arrays - right now you really only have to know how to access the first element which is in index 0.We do this by specifiying args[0]. The first element in an array in Java is always index 0. Some other languages, such as Pascal, give you a lot more freedom in specifying the index structure of an array.

So now we know that the year will be accessible through args[0]. I personally don't like having to remember what the argument array is holding in what element - so the first thing I do is store them into variables that I give. This allows me to reference the value through a meaningful name.

So the next line in our main method will be a variable declaration. Since we're expecting year - we'll call it year, also since args is of type String - we'll make year as type String.

String year;

Now we need to assign args[0] to the variable year.

year= args[0];

Finally, we want to call convertYear(). We'll need to pass the year to the method, since the convertYear method will not know anything about the year variable in main. You saw this in SmartHello - so it shouldn't be too new. We also need to prefix convertYear() with the object yearToRomanNumerals.

yearToRomanNumerals.convertYear(year);

So now the YearToRomanNumerals class looks like this -

public class YearToRomanNumerals
{  public state void main(String[] args)
   { YearToRomanNumerals yearToRomanNumerals= new YearToRomanNumerals();
     String year;

     year= args[0];
     yearToRomanNumerals.convertYear(year);
   }

Now lets move onto building the convertYear method. This method will have no real logic in it. It'll basically call the four methods that will return the respective Roman Numerals, concatenate or combine those Roman Numerals together to form the year and then print a message out to the user.

Let's start with the method signature line. We'll keep the method private for now, and the method's not returning anything - so the return value will be void, the name will be convertYear and we are accepting as an argument a string that represents the year. Translated into Java - we should have...

private void convertYear(String year)

Now to develop the body of the method. First we need several variables. One to hold the Roman Numeral year and four others that will hold the Roman Numeral for each number that makes up the year. We will call these variables - romanNumeral, ones, tens, hundreds and thousands. All of these variables will be of type String. So let's define these and don't forget the beginning brace for the method.

{  String ones,
          tens,
          hundreds,
          thousands
          romanNumeral;

Now it's time to call the methods that will actually process the year and break it apart. Each method will be returning a Roman Numeral. This Roman Nmeral will be either held by the variable ones, tens, hundreds or thousands. Again we will have to pass the year.

   ones= getOnes(year);
   tens= getTens(year);
   hundreds= getHundreds(year);
   thousands= getThousands(year);

 

Let's explain what will happen in the above code - or at least what should happen. Let's take the year 1987 again. First 1987 will be passed to the getOnes method. This will then process the year and return the ones digit in the Roman Numeral format, in this case "VII". So "VII" will be stored in the variable ones. Next it will process the tens- it will pass year into the getTens method and return back the Roman Numeral for the tens place in the year. It should pass back " DXXX". It will repeat this process for the hundreds and the thousands. The getHundreds method should return "CM" and the getThousands method should return "M".

We now need to concatenate these to form the Roman Numeral year. This is accomplished by adding the returned strings together. We want to store these combined variables into the variable romanNumeral. This is what we should have now....

   romanNumeral= thousands + hundreds + tens + ones;

After this - romanNumeral should hold 1987 in Roman Numeral format or "MCMDXXXVII".

Now we need to report this back to the user. You should report something meaningful back to the user, so let's say something like this - "Year 1987 equals MCMDXXXVII in Roman Numeral format.". Of course we need the actual year and the Roman Numeral year to change based on what the user enters in and the program calculates - so we'll replace those with their respective variables - "year" and "romanNumeral". So finally we have -

   System.out.println("Year "+year+" equals "+romanNumeral+" in Roman Numeral format.");
}

Now let's figure out how to process the year into Roman Numerals. We'll need to create the signature of the method. Again we'll give it a private scope. Since it'll be returning a String back to convertYear - we'll need to sepecify the return type as String. As we said earlier the name will be getOnes and it will accept a String as it's argument for the year. So this is what we should have...

private String getOnes(String year)
{

Now we need to code the body of the method. First we need a couple of variables - one to store the Roman Numeral and the other to store the digit that we get from the year. These we will call romanNumeral and digit. We'll initialize romanNumeral as "" or blank - it'll make it easier to handle a digit of 0. The other thing we will have to do is obtain the proper digit from the year. Since this will return one character, we will declare digit of type char. In order to get the proper digit, we will use the charAt method that is in the String class. This is the format af the charAt method - string.charAt(locationOfCharacter). The first character is at location 0, the right most character would be at location - numberOfCharacters - 1. So this is what we have.

   char digit;
   String romanNumeral= "";

   digit= year.charAt(3); //This will get the 4th character in the year. If year is 1987 - then it will return 7.

Now we need to convert this digit into it's corresponding Roman Numeral. Since we're working with the ones place right now - we want to limit our function to only deal with the Roman Numerals I to IX. To do the conversion we could use multiple if statements like we did in our pseudo code - but the switch statement is designed for this type of problem. Here is the format for the swicth statement.

switch(variable)
{  case equalsValue:
       code for body of case statement;
       break;
    case equalsValue2:
       code for body of case statement;
       break;
    default:
       code for body of default statement;
}

With the swicth statement we can easily convert the digit to it's corresponding digit. I'll leave the numbers 5 to 7 up to you, but this will give you an idea of how to code it.

   switch(digit)
   {  case '0':
        break; // since we initialized romanNumeral to ""- it will automatically handle the 0.
      case '1':
        romanNumeral= "I";
        break; // we need to use break so it doesn't "fall through" to the next case. MAKE SURE you watch for this.
      case '2':
        romanNumeral= "II";
        break;
      case '3':
        romanNumeral= "III";
        break;
      •
      •
      case '8':
        romanNumeral= "VIII";
        break;
      case '9':
        romanNumeral= "IX";
        break;
      default:
        romanNumeral= "ERROR"; //This is to notify the user that there was some sort of error.
   }

Now we need to return the Roman Numeral back to the calling method, in this case - convertYear(), and close the method with the ending curly brace.

   return romanNumeral;
}

YearToRomanNumerals.java

public class YearToRomanNumerals
{  public static void main(String[] args)
   {  YearToRomanNumerals yearToRomanNumerals= new YearToRomanNumerals();
      String year;

            year= args[0];
      if (year.length()<4 || year.length()>4)
        System.out.println("Year must be between 1000 and 9999. Please restart with valid year");
      else
        yearToRomanNumerals.convertYear(year);
   }

   private void convertYear(String year)
   {  String romanNumeral;

      romanNumeral= getRomanNumeral(year);
      System.out.println("Year "+year+ " equals "+romanNumeral+" in Roman Numeral Format");
   }

   private String getRomanNumeral(String year)
   {  String ones,
             tens,
             hundreds,
             thousands,
             romanNumeral;

      ones= getOnes(year);
      tens= getTens(year);
      hundreds= getHundreds(year);
      thousands= getThousands(year);

      romanNumeral= thousands+hundreds+tens+ones;

      return romanNumeral;
   }

   private String getOnes(String year)
   {  char digit;
      String romanNumeral= "";

      digit= year.charAt(3);

      switch(digit)
      {  case '0':
           break;
         case '1':
           romanNumeral= "I";
           break;
         case '2':
           romanNumeral= "II";
           break;
         case '3':
           romanNumeral= "III";
           break;
         case '4':
           romanNumeral= "IV";
           break;
         case '5':
           romanNumeral= "V";
           break;
         case '6':
           romanNumeral= "VI";
           break;
         case '7':
           romanNumeral= "VII";
           break;
         case '8':
           romanNumeral= "VIII";
           break;
         case '9':
           romanNumeral= "IX";
           break;
         default:
           romanNumeral= "ERROR";
           break;
      }

      return romanNumeral;
   }

   private String getTens(String year)
   {  char digit;
      String romanNumeral= "";

      digit= year.charAt(2);

      switch(digit)
      {  case '0':
           break;
         case '1':
           romanNumeral= "X";
           break;
         case '2':
           romanNumeral= "XX";
           break;
         case '3':
           romanNumeral= "XXX";
           break;
         case '4':
           romanNumeral= "XL";
           break;
         case '5':
           romanNumeral= "L";
           break;
         case '6':
           romanNumeral= "LX";
           break;
         case '7':
           romanNumeral= "LXX";
           break;
         case '8':
           romanNumeral= "LXXX";
           break;
         case '9':
           romanNumeral= "XC";
           break;
         default:
           romanNumeral= "ERROR";
           break;
      }

      return romanNumeral;
   }

   private String getHundreds(String year)
   {  char digit;
      String romanNumeral= "";

      digit= year.charAt(1);

      switch(digit)
      {  case '1':
           romanNumeral= "C";
           break;
         case '2':
           romanNumeral= "CC";
           break;
         case '3':
           romanNumeral= "CCC";
           break;
         case '4':
           romanNumeral= "CD";
           break;
         case '5':
           romanNumeral= "D";
           break;
         case '6':
           romanNumeral= "DC";
           break;
         case '7':
           romanNumeral= "DCC";
           break;
         case '8':
           romanNumeral= "DCCC";
           break;
         case '9':
           romanNumeral= "CM";
           break;
         default:
           romanNumeral= "ERROR";
           break;
      }

      return romanNumeral;
   }

   private String getThousands(String year)
   {  char digit;
      String romanNumeral= "";

      digit= year.charAt(0);

      switch(digit)
      {  case '1':
           romanNumeral= "M";
           break;
         case '2':
           romanNumeral= "MM";
           break;
         case '3':
           romanNumeral= "MMM";
           break;
         case '4':
           romanNumeral= "MMMM";
           break;
         default:
           romanNumeral= "***Sorry - Unable to go above 4999*** "+year.substring(1)+" is ";
           break;
      }

      return romanNumeral;
   }
}

 

<-Java Tutorial - The Basics