Converting Roman Numerals To Decimal

2019-01-01 15:54发布

I have managed to get my code to convert most Roman numerals to its appropriate decimal value. But it doesn't work for some exceptional cases. Example : XCIX = 99 but my code prints 109.

Here is my code.

public static int romanConvert(String roman)
{
    int decimal = 0;

    String romanNumeral = roman.toUpperCase();
    for(int x = 0;x<romanNumeral.length();x++)
    {
        char convertToDecimal = roman.charAt(x);

        switch (convertToDecimal)
        {
        case 'M':
            decimal += 1000;
            break;

        case 'D':
            decimal += 500;
            break;

        case 'C':
            decimal += 100;
            break;

        case 'L':
            decimal += 50;
            break;

        case 'X':
            decimal += 10;
            break;

        case 'V':
            decimal += 5;
            break;

        case 'I':
            decimal += 1;
            break;
        }
    }
    if (romanNumeral.contains("IV"))
    {
        decimal-=2;
    }
    if (romanNumeral.contains("IX"))
    {
        decimal-=2;
    }
    if (romanNumeral.contains("XL"))
    {
        decimal-=10;
    }
    if (romanNumeral.contains("XC"))
    {
        decimal-=10;
    }
    if (romanNumeral.contains("CD"))
    {
        decimal-=100;
    }
    if (romanNumeral.contains("CM"))
    {
        decimal-=100;
    }
    return decimal;
}

标签: java
26条回答
孤独寂梦人
2楼-- · 2019-01-01 16:01

this is very basic implementation of what you asked and working for all the test cases. If you find anything wrong in it than do mention it,i will try to make it correct also the code is in C++ .

int RomanToInt(string s){ 
    int len = s.length();
    map<char,int>mp;
    int decimal = 0;
    mp['I'] = 1;mp['V'] = 5;mp['X'] = 10;
    mp['L'] = 50;mp['C'] = 100;mp['D'] = 500;mp['M'] = 1000;
    for(int i = 0; i < len ;i++){
       char cur = s[i],fast = s[i+1];
       int cur_val = mp[cur],fast_val = mp[fast];
       if(cur_val < fast_val){
          decimal = decimal - cur_val;
       }else{
          decimal += cur_val;
       }
    }
    return decimal;
}
查看更多
浅入江南
3楼-- · 2019-01-01 16:02

Lets look at this problem with 3 different scenarios

Scenario 1:

When we see a pattern like the following

'IIIIII' or 'XXXXX'  or 'CCCC'

where all characters as the same: We add the value of each characters in the pattern

'IIIIII' gives us '6'

'XXXXX' gives us '50'

'CCCC' gives us '400'

Scenario 2:

When we see any 2 consecutive characters different where first is smaller in value then the 2nd

'IX' or 'XC'

We subtract the value of first from second e.g.

second:'X' gives us '10'

first: 'I' gives us '1'

second  - first :  10 - 1 = 9

Scenario 3:

When we see a any 2 consecutive characters different where first is greater in value then the second

'XI' or 'CX'

We add first and second e.g.

second:'I' gives us '10'
first: 'X' gives us '1'
first  + second :  10 +  1 = 11

Now we can find the result if we do this recursively. Here is the java implementation :

//An array to be used for faster comparisons and reading the values
private int[] letters26 = new int[26];
private void init () {
    letters26['I' - 'A'] = 1;
    letters26['V' - 'A'] = 5;
    letters26['X' - 'A'] = 10;
    letters26['L' - 'A'] = 50;
    letters26['C' - 'A'] = 100;
    letters26['D' - 'A'] = 500;
    letters26['M' - 'A'] = 1000;
}

public int convertRomanToInteger(String s) {
    //Initialize the array
    init();
    return _convertRomanToInteger(s.toCharArray(), 0);
}

//Recursively  calls itself as long as 2 consecutive chars are different
private int _convertRomanToInteger(char[] s, int index) {
    int ret = 0;
    char pre = s[index];//Char from the given index
    ret = _getValue(pre);

    //Iterate through the rest of the string 
    for (int i = index + 1; i < s.length; i++) {
        if (compare(s[i], s[i - 1]) == 0) {
            //Scenario 1:
            //If 2 consecutive chars are similar, just add them             
            ret += _getValue(s[i]);
        } else if (compare(s[i], s[i - 1]) > 0) {
            //Scenario 2:
            //If current char is greater than the previous e.g IX ('I' s[i - 1] and 'X' s[i - 1])
            //We need to calculate starting from 'i' and subtract the calculation ('ret') 
            //done so far in current call
            return _convertRomanToInteger(s, i) - ret;
        } else {
            //Scenario 3:
            //If current char is smaller than the previous e.g XI ('X' s[i - 1] and 'I' s[i - 1])
            //We need to calculate starting from 'i' and subtract the result 
            //from the calculation done so far in current call
            return ret + _convertRomanToInteger(s, i);
        }
    }
    return ret;
}

//Helper function for comparison
private int compare(char a, char b) {
    return letters26[Character.toUpperCase(a) - 'A']
            - letters26[Character.toUpperCase(b) - 'A'];
}

private int _getValue(char c) {
    return letters26[Character.toUpperCase(c) - 'A']; 
}
查看更多
流年柔荑漫光年
4楼-- · 2019-01-01 16:04

Try this - It is simple and compact and works quite smoothly:

    public static int ToArabic(string number) {
        if (number == string.Empty) return 0;
        if (number.StartsWith("M")) return 1000 + ToArabic(number.Remove(0, 1));
        if (number.StartsWith("CM")) return 900 + ToArabic(number.Remove(0, 2));
        if (number.StartsWith("D")) return 500 + ToArabic(number.Remove(0, 1));
        if (number.StartsWith("CD")) return 400 + ToArabic(number.Remove(0, 2));
        if (number.StartsWith("C")) return 100 + ToArabic(number.Remove(0, 1));
        if (number.StartsWith("XC")) return 90 + ToArabic(number.Remove(0, 2));
        if (number.StartsWith("L")) return 50 + ToArabic(number.Remove(0, 1));
        if (number.StartsWith("XL")) return 40 + ToArabic(number.Remove(0, 2));
        if (number.StartsWith("X")) return 10 + ToArabic(number.Remove(0, 1));
        if (number.StartsWith("IX")) return 9 + ToArabic(number.Remove(0, 2));
        if (number.StartsWith("V")) return 5 + ToArabic(number.Remove(0, 1));
        if (number.StartsWith("IV")) return 4 + ToArabic(number.Remove(0, 2));
        if (number.StartsWith("I")) return 1 + ToArabic(number.Remove(0, 1));
        throw new ArgumentOutOfRangeException("something bad happened");
    }
查看更多
冷夜・残月
5楼-- · 2019-01-01 16:04

This scala solution might be useful:

class RomanNumberConverter {

  private val toArabic = Map('I' -> 1, 'V' -> 5, 'X' -> 10, 'L' -> 50, 'C' -> 100, 'D' -> 500, 'M' -> 1000)

  // assume that correct roman number is provided
  def convert(romanNumber: String): Int = {
    def convert(rn: StringBuilder, lastDecimal: Int, acc: Int): Int = {
      if (rn.isEmpty) acc
      else {
        val thisDecimal = toArabic(rn.head)
        if (thisDecimal > lastDecimal) convert(rn.tail, thisDecimal, acc + thisDecimal - lastDecimal - lastDecimal)
        else convert(rn.tail, thisDecimal, acc + thisDecimal)
      }
    }

    val sb = new StringBuilder(romanNumber)
    convert(sb.tail, toArabic(sb.head), toArabic(sb.head))
  }

}
查看更多
几人难应
6楼-- · 2019-01-01 16:05

Here is my one...

import java.util.Scanner;
class Solution {

public static void main(String args[]) {

     Scanner sc = new Scanner(System.in);

    String num;

   //  System.out.println("enter the number you want to convert from roman to integer.");

     num = "D";
    System.out.println("length of string is " + num.length());

    System.out.println("the integer number is :" + romanToInt(num) );
}

public static int romanToInt(String s) {

    char I,V, X, L,C, D, M;

    char c1,c3, c2 = s.charAt(0);
   // System.out.println("the c2 is : " + (int)c2);
    int num = 0, num1 = 0;
    int j =0, k = 0, temp = 0;

     if (c2 == 'I') {
            k = (int)c2 - 72;
            System.out.println("k is I" + k);
        } else if(c2 == 'V') {
            k = (int)c2 - 81;
            System.out.println("K is V" + k);
           // return 86 - 81;
        } else if (c2 == 'X') {
             k = (int)c2 - 78;
            System.out.println("K is X" + k);
        } else if (c2 == 'L') {
            k = (int)c2 - 26;
            System.out.println("K is L" + k);
        } else if (c2 == 'C') {
            k = (int)c2 + 33;
            System.out.println("K is C" + k);
        } else if (c2 == 'D') {
             k = (int)c2 + 432;
            System.out.println("K is D" + k);
        } else if ( c2 == 'M') {
             k = (int)c2 + 923;
            System.out.println("K is M" + k);
        }
     if (s.length() == 1){
         num = k;

     } else {
           for(int i = 1; i<= s.length()-1  ; i++) {
        System.out.println("i is : " + i);
         c1 = s.charAt(i);
        if (i == s.length() - 1) {
           temp = 0; 
        } else  {
             c3 = s.charAt(i+1);
             if (c3 == 'I') {

            temp = (int)c3 - 72;
            System.out.println("temp is I " + temp);
        } else if(c3 == 'V') {
            temp = (int)c3 - 81;
            System.out.println("temp is I " + temp);
           // return 86 - 81;
        } else if (c3 == 'X') {
             temp = (int)c3 - 78;
             System.out.println("temp is I " + temp);
        } else if (c3 == 'L') {
            temp = (int)c3 - 26;
             System.out.println("temp is I " + temp);
        } else if (c3 == 'C') {
            temp = (int)c3 + 33;
            System.out.println("temp is I " + temp);
        } else if (c3 == 'D') {
             temp = (int)c3 + 432;
             System.out.println("temp is I " + temp);
        } else if ( c3 == 'M') {
             temp = (int)c3 + 923;
             System.out.println("temp is I " + temp);
        }
        }


        if (c1 == 'I') {

            j = (int)c1 - 72;
            System.out.println("j is I " + j);
        } else if(c1 == 'V') {
            j = (int)c1 - 81;
            System.out.println("j is V " + j);
           // return 86 - 81;
        } else if (c1 == 'X') {
             j = (int)c1 - 78;
            System.out.println("j is X " + j);
        } else if (c1 == 'L') {
            j = (int)c1 - 26;
            System.out.println("j is L " + j);
        } else if (c1 == 'C') {
            j = (int)c1 + 33;
            System.out.println("j is C " + j);
        } else if (c1 == 'D') {
             j = (int)c1 + 432;
            System.out.println("j is D " + j);
        } else if ( c1 == 'M') {
             j = (int)c1 + 923;
            System.out.println("j is M " + j);
        }

        if ( k < j && j>temp ) {
           k = j - k ;
          num = num + k;


        } else if (j==k || j<k || j<temp){

               num = num + k ; 
           //   k = j;
        }

        if (j>k ) {
            k = temp;
            i += 1;

            if (i == s.length()-1) {
                num = num + k;
            }
        } else {
            k = j;
            if (i == s.length()-1) {
                num = num + k;
            }

        }



     }

  }   

    return num;                         
   }

}
查看更多
回忆,回不去的记忆
7楼-- · 2019-01-01 16:06
//Bet no one has a smaller and easier logic than this........Open CHALLENGE!!!!!!!
import java.io.*;
class Convertion_practical_q2
{
void Decimal()throws IOException //Smaller code for convertion from roman to decimal
{
    DataInputStream in=new DataInputStream(System.in);
    System.out.println("Enter the number");
    String num=in.readLine();
    char pos[]={'0','I','V','X','L','C','D','M'};   
    int l1=7;                           //l1 is size of pos array
    String v[]={"","1","5","10","50","100","500","1000"};
    int l=num.length();
    int p=0,p1=0,sum=0;

    for(int i=l-1;i>=0;i--)
    {
        char ch=num.charAt(i);
        for(int j=1;j<=l1;j++)
        {
            if(ch==pos[j])
            p=j;
        }
        if(p>=p1)
            sum+=Integer.parseInt(v[p]);
        else
            sum-=Integer.parseInt(v[p]);
            //System.out.println("sum ="+sum+"\np="+p+"\np1="+p1);
            p1=p;
    }
    System.out.println(sum);
}
}
查看更多
登录 后发表回答