Converting Roman Numerals to Decimal

Converting Roman Numerals To Decimal

It will be good if you traverse in reverse.

public class RomanToDecimal {
public static void romanToDecimal(java.lang.String romanNumber) {
int decimal = 0;
int lastNumber = 0;
String romanNumeral = romanNumber.toUpperCase();
/* operation to be performed on upper cases even if user
enters roman values in lower case chars */
for (int x = romanNumeral.length() - 1; x >= 0 ; x--) {
char convertToDecimal = romanNumeral.charAt(x);

switch (convertToDecimal) {
case 'M':
decimal = processDecimal(1000, lastNumber, decimal);
lastNumber = 1000;
break;

case 'D':
decimal = processDecimal(500, lastNumber, decimal);
lastNumber = 500;
break;

case 'C':
decimal = processDecimal(100, lastNumber, decimal);
lastNumber = 100;
break;

case 'L':
decimal = processDecimal(50, lastNumber, decimal);
lastNumber = 50;
break;

case 'X':
decimal = processDecimal(10, lastNumber, decimal);
lastNumber = 10;
break;

case 'V':
decimal = processDecimal(5, lastNumber, decimal);
lastNumber = 5;
break;

case 'I':
decimal = processDecimal(1, lastNumber, decimal);
lastNumber = 1;
break;
}
}
System.out.println(decimal);
}

public static int processDecimal(int decimal, int lastNumber, int lastDecimal) {
if (lastNumber > decimal) {
return lastDecimal - decimal;
} else {
return lastDecimal + decimal;
}
}

public static void main(java.lang.String args[]) {
romanToDecimal("XIV");
}
}

Convert roman numerals to decimal value error

You forgot to call valueOf() in the else branch:

...

} else {
total += valueOf(romanNum.charAt(1)) - valueOf(romanNum.charAt(0));
romanNum = romanNum.substring(2);
}

How to convert Roman numerals into decimal numbers?

Just for fun, an alternative that splits the string into the groups of single and adjacent numerals, allowing for standard subtractive notation (thank you, Wikipedia; converts each single or adjacent pairs or numerals into their decimal equivalents; and then sums them:

with t (str) as (select 'MCMLXXXIV' from dual)
select sum(
case regexp_substr(str, '(CM|M|CD|D|XC|C|XL|L|IX|X|IV|V|I)', 1, level)
when 'M' then 1000
when 'CM' then 900
when 'D' then 500
when 'CD' then 400
when 'C' then 100
when 'XC' then 90
when 'L' then 50
when 'XL' then 40
when 'X' then 10
when 'IX' then 9
when 'V' then 5
when 'IV' then 4
when 'I' then 1
end) as decimals
from t
connect by regexp_substr(str, '(CM|M|CD|D|XC|C|XL|L|IX|X|IV|V|I)', 1, level) is not null;

DECIMALS
----------
1984

Notice that the order of the search terms in the regex isn't the same as their equivalent decimal order; you need to match CM bfore M because of the subtractive notation.

If this is something you need to do a lot it's probably worth creating a deterministic function (which is true with the recursive CTE method too, of course). In which case you could switch to a PL/SQL loop to cut down on context switches:

create or replace function roman_to_decimal(p_roman varchar2)
return number deterministic is
l_decimal number := 0;
begin
for i in 1..regexp_count(p_roman, '(CM|M|CD|D|XC|C|XL|L|IX|X|IV|V|I)') loop
l_decimal := l_decimal +
case regexp_substr(p_roman, '(CM|M|CD|D|XC|C|XL|L|IX|X|IV|V|I)', 1, i)
when 'M' then 1000
when 'CM' then 900
when 'D' then 500
when 'CD' then 400
when 'C' then 100
when 'XC' then 90
when 'L' then 50
when 'XL' then 40
when 'X' then 10
when 'IX' then 9
when 'V' then 5
when 'IV' then 4
when 'I' then 1
end;
end loop;

return l_decimal;
end;
/

select roman_to_decimal('DXV'), roman_to_decimal('MCMLXXXIV')
from dual;

ROMAN_TO_DECIMAL('DXV') ROMAN_TO_DECIMAL('MCMLXXXIV')
----------------------- -----------------------------
515 1984

You can see and check all the conversions (1-3999, as that is the range supported by to_char()) with:

with t (orig, roman) as (
select level, to_char(level, 'RN') from dual connect by level < 4000
)
select orig, roman, roman_to_decimal(roman)
from t;

ORIG ROMAN ROMAN_TO_DECIMAL(ROMAN)
---------- --------------- -----------------------
1 I 1
2 II 2
3 III 3
4 IV 4
5 V 5
6 VI 6
7 VII 7
8 VIII 8
9 IX 9
10 X 10
11 XI 11
...
3994 MMMCMXCIV 3994
3995 MMMCMXCV 3995
3996 MMMCMXCVI 3996
3997 MMMCMXCVII 3997
3998 MMMCMXCVIII 3998
3999 MMMCMXCIX 3999

Or just to verify they all convert back to their original values:

with t (original, roman) as (
select level, to_char(level, 'RN') from dual connect by level < 4000
)
select original, roman, roman_to_decimal(roman)
from t
where roman_to_decimal(roman) != original;

no rows selected

This is very slightly slower than the recursive CTE equivalent for me, but might differ on other versiosn and platforms; and like I said, just for fun...

Convert Roman Numerals to decimal numbers in C

If there are at least 3 letters starting at offset i, and the third has a value larger than the first, the roman number is invalid.

If the value of the letter is less than the value of the next letter, subtract the value of the first from the value of the second, add this to the total and skip both.

Otherwise, add the value of the current letter to the total.

These statements should be inside the body of a for loop that iterates i from 0 to the length of the string roman_Number.

Octave/MATLAB Function to Convert Roman Numeral Into Decimal Number

As far as I can tell the only rule you need to worry about is determining if the letter constitutes an "add" or "subtract" operation. For some letter, we only subtract it if the first non-equal letter to the right represents a greater value.

For example in 'IIV' The first non-equal letter to the right of both I's is V so we subtract 2 and add 5 for the V since it has no letters to the right.

Implementing this rule in MATLAB is fairly straightforward.

function num = roman2num(s)
decimal = [1000, 500, 100, 50, 10, 5, 1];
roman = ['M', 'D', 'C', 'L', 'X', 'V', 'I'];
tokens = arrayfun(@(x) decimal(find(roman==x,1)), char(s));
num = tokens(end);
for idx = 1:numel(tokens)-1
val = tokens(idx);
ridx = find(tokens(idx+1:end) ~= val, 1);
if ~isempty(ridx) && tokens(ridx + idx) > val
num = num - val;
else
num = num + val;
end
end

I tested using all the numerals between 1 and 3333.



Related Topics



Leave a reply



Submit