我设法让我的代码将大多数罗马数字转换为适当的十进制值。但它不适用于某些特殊情况。示例:XCIX
= 99
,但我的代码打印为109
。
这是我的代码。
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;
}
答案 0 :(得分:57)
如果你反过来走路会很好。
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");
}
}
答案 1 :(得分:39)
试试这个 - 它简单而紧凑,工作非常顺利:
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");
}
答案 2 :(得分:24)
假设哈希看起来像这样
Hashtable<Character, Integer> ht = new Hashtable<Character, Integer>();
ht.put('i',1);
ht.put('x',10);
ht.put('c',100);
ht.put('m',1000);
ht.put('v',5);
ht.put('l',50);
ht.put('d',500);
然后逻辑变得非常简单,从右到左依次为
public static int rtoi(String num)
{
int intNum=0;
int prev = 0;
for(int i = num.length()-1; i>=0 ; i--)
{
int temp = ht.get(num.charAt(i));
if(temp < prev)
intNum-=temp;
else
intNum+=temp;
prev = temp;
}
return intNum;
}
答案 3 :(得分:4)
遵循在IX上减少2的逻辑,你应该在CM上的XC 200上减少20,依此类推。
答案 4 :(得分:3)
代码更少,效率更高。不太清楚,抱歉!
public int evaluateRomanNumerals(String roman) {
return (int) evaluateNextRomanNumeral(roman, roman.length() - 1, 0);
}
private double evaluateNextRomanNumeral(String roman, int pos, double rightNumeral) {
if (pos < 0) return 0;
char ch = roman.charAt(pos);
double value = Math.floor(Math.pow(10, "IXCM".indexOf(ch))) + 5 * Math.floor(Math.pow(10, "VLD".indexOf(ch)));
return value * Math.signum(value + 0.5 - rightNumeral) + evaluateNextRomanNumeral(roman, pos - 1, value);
}
答案 5 :(得分:3)
为了避免无用的计算并确保罗马数字格式正确,我们需要使用正则表达式检查输入。
String regex = "^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$";
势在必行的解决方案
public static int romanToDecimal(String s) {
if (s == null || s.isEmpty() || !s.matches("^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
return -1;
final Matcher matcher = Pattern.compile("M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I").matcher(s);
final int[] decimalValues = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
final String[] romanNumerals = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int result = 0;
while (matcher.find())
for (int i = 0; i < romanNumerals.length; i++)
if (romanNumerals[i].equals(matcher.group(0)))
result += decimalValues[i];
return result;
}
try online | try optimized version with comments/explanation online
更新:这里有两个聪明的递归提案,我解决了添加验证步骤
递归解决方案1 (original answer)
public class RomanToDecimalConverter {
private static double evaluateNextRomanNumeral(String roman, int pos, double rightNumeral) {
if (pos < 0) return 0;
char ch = roman.charAt(pos);
double value = Math.floor(Math.pow(10, "IXCM".indexOf(ch))) + 5 * Math.floor(Math.pow(10, "VLD".indexOf(ch)));
return value * Math.signum(value + 0.5 - rightNumeral) + evaluateNextRomanNumeral(roman, pos - 1, value);
}
public static int evaluateRomanNumerals(String s) {
if (s == null || s.isEmpty() || !s.matches("^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
return -1;
return (int) evaluateNextRomanNumeral(s, s.length() - 1, 0);
}
}
递归解决方案2 (original answer)
public class RomanToDecimalConverter {
private static int convertRec(String s) {
if (s.isEmpty()) return 0;
if (s.startsWith("M")) return 1000 + convertRec(s.substring(1));
else if (s.startsWith("CM")) return 900 + convertRec(s.substring(2));
else if (s.startsWith("D")) return 500 + convertRec(s.substring(1));
else if (s.startsWith("CD")) return 400 + convertRec(s.substring(2));
else if (s.startsWith("C")) return 100 + convertRec(s.substring(1));
else if (s.startsWith("XC")) return 90 + convertRec(s.substring(2));
else if (s.startsWith("L")) return 50 + convertRec(s.substring(1));
else if (s.startsWith("XL")) return 40 + convertRec(s.substring(2));
else if (s.startsWith("X")) return 10 + convertRec(s.substring(1));
else if (s.startsWith("IX")) return 9 + convertRec(s.substring(2));
else if (s.startsWith("V")) return 5 + convertRec(s.substring(1));
else if (s.startsWith("IV")) return 4 + convertRec(s.substring(2));
else if (s.startsWith("I")) return 1 + convertRec(s.substring(1));
throw new IllegalArgumentException("Unexpected roman numerals");
}
public static int convert(String s) {
if (s == null || s.isEmpty() || !s.matches("^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
return -1;
return convertRec(s);
}
}
答案 6 :(得分:2)
// Author: Francisco Edmundo
private int translateNumber(String texto) {
int n = 0;
int numeralDaDireita = 0;
for (int i = texto.length() - 1; i >= 0; i--) {
int valor = (int) translateNumber(texto.charAt(i));
n += valor * Math.signum(valor + 0.5 - numeralDaDireita);
numeralDaDireita = valor;
}
return n;
}
private double translateNumber(char caractere) {
return Math.floor(Math.pow(10, "IXCM".indexOf(caractere))) + 5 * Math.floor(Math.pow(10, "VLD".indexOf(caractere)));
}
答案 7 :(得分:2)
您可以查看以下代码。此代码应适用于所有情况。它还会检查null或空输入和错误输入(假设您尝试使用ABXI)
import java.util.HashMap;
import org.apache.commons.lang3.StringUtils;
public class RomanToDecimal {
private HashMap<Character, Integer> map;
public RomanToDecimal() {
map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
}
private int getRomanNumeralValue(char ch) {
if (map.containsKey(ch)) {
return map.get(ch);
}
else {
throw new RuntimeException("Roman numeral string contains invalid characters " + ch);
}
}
public int convertRomanToDecimal(final String pRomanNumeral) {
if (StringUtils.isBlank(pRomanNumeral)) {
throw new RuntimeException("Roman numeral string is either null or empty");
}
else {
int index = pRomanNumeral.length() - 1;
int result = getRomanNumeralValue(pRomanNumeral.charAt(index));
for (int i = index - 1; i >= 0; i--) {
if (getRomanNumeralValue(pRomanNumeral.charAt(i)) >= getRomanNumeralValue(pRomanNumeral.charAt(i + 1))) {
result = result + getRomanNumeralValue(pRomanNumeral.charAt(i));
}
else {
result = result - getRomanNumeralValue(pRomanNumeral.charAt(i));
}
}
return result;
}
}
public static void main(String... args){
System.out.println(new RomanToDecimal().convertRomanToDecimal("XCIX"));
}
}
答案 8 :(得分:1)
尽管已经提出了许多解决方案。
我想下面的内容简短明了:
public class RomanToInteger {
public static int romanToInt(String roman) {
final Map<Character, Integer> map = Map.of('I', 1,
'V', 5,
'X', 10,
'L', 50,
'C', 100,
'D', 500,
'M', 1000);
int result = 0;
for (int index = 0; index < roman.length(); index++) {
final int curNumber = map.get(roman.charAt(index));
if (index > 0 && curNumber > map.get(roman.charAt(index - 1))) {
// add current number & remove previous one twice:
// first: we add it before (when it was current number) and removing it for this current number
// second: for correct conversion to roman numbers
result += curNumber - 2 * map.get(roman.charAt(index - 1));
} else {
result += curNumber;
}
}
System.out.printf("%8s -> %4d\n", roman, result);
return result;
}
public static void main(String[] args) {
String[] romans = {"I", "II", "III", "V", "X", "XIV", "XVII", "XX", "XXV",
"XXX", "XXXVIII", "XLIX", "LXIII", "LXXXI", "XCVII", "XCVIII", "XCIX",
"C", "CI", "CCXLVIII", "CCLIII", "DCCXCIX", "MCCCXXV", "MCM", "MM",
"MMCDLVI", "MDCCXV"};
final Instant startTimeIter = Instant.now();
for (String roman : romans) {
romanToInt(roman);
}
final Instant endTimeIter = Instant.now();
System.out.printf("Elapsed time: %d ms\n", Duration.between(startTimeIter, endTimeIter).toMillis());
}
}
输出:
I -> 1
II -> 2
III -> 3
...
MMCDLVI -> 2456
MDCCXV -> 1715
Elapsed time: 101 ms
逻辑很简单,我们只需从左到右通过罗马文字:
IX
文字)。答案 9 :(得分:1)
具有错误检查功能的完整版本,并在两个方向(以及一些无效情况)下测试所有有效值。
RomanNumeral.java
import java.util.ArrayList;
import java.util.TreeMap;
/**
* Convert to and from a roman numeral string
*/
public class RomanNumeral {
// used for converting from arabic number
final static TreeMap<Integer, String> mapArabic = new TreeMap<Integer, String>();
// used for converting from roman numeral
final static ArrayList<RomanDigit> mapRoman = new ArrayList<RomanDigit>();
final static int MAX_ARABIC = 3999;
static {
mapArabic.put(1000, "M");
mapArabic.put(900, "CM");
mapArabic.put(500, "D");
mapArabic.put(400, "CD");
mapArabic.put(100, "C");
mapArabic.put(90, "XC");
mapArabic.put(50, "L");
mapArabic.put(40, "XL");
mapArabic.put(10, "X");
mapArabic.put(9, "IX");
mapArabic.put(5, "V");
mapArabic.put(4, "IV");
mapArabic.put(1, "I");
mapRoman.add(new RomanDigit("M", 1000, 3, 1000));
mapRoman.add(new RomanDigit("CM", 900, 1, 90));
mapRoman.add(new RomanDigit("D", 500, 1, 100));
mapRoman.add(new RomanDigit("CD", 400, 1, 90));
mapRoman.add(new RomanDigit("C", 100, 3, 100));
mapRoman.add(new RomanDigit("XC", 90, 1, 9));
mapRoman.add(new RomanDigit("L", 50, 1, 10));
mapRoman.add(new RomanDigit("XL", 40, 1, 9));
mapRoman.add(new RomanDigit("X", 10, 3, 10));
mapRoman.add(new RomanDigit("IX", 9, 1, 0));
mapRoman.add(new RomanDigit("V", 5, 1, 1));
mapRoman.add(new RomanDigit("IV", 4, 1, 0));
mapRoman.add(new RomanDigit("I", 1, 3, 1));
}
static final class RomanDigit {
public final String numeral;
public final int value;
public final int maxConsecutive;
public final int maxNextValue;
public RomanDigit(String numeral, int value, int maxConsecutive, int maxNextValue) {
this.numeral = numeral;
this.value = value;
this.maxConsecutive = maxConsecutive;
this.maxNextValue = maxNextValue;
}
}
/**
* Convert an arabic integer value into a roman numeral string
*
* @param n The arabic integer value
* @return The roman numeral string
*/
public final static String toRoman(int n) {
if (n < 1 || n > MAX_ARABIC) {
throw new NumberFormatException(String.format("Invalid arabic value: %d, must be > 0 and < %d", n, MAX_ARABIC));
}
int leDigit = mapArabic.floorKey(n);
//System.out.println("\t*** floor of " + n + " is " + leDigit);
if (n == leDigit) {
return mapArabic.get(leDigit);
}
return mapArabic.get(leDigit) + toRoman(n - leDigit);
}
/**
* Convert a roman numeral string into an arabic integer value
* @param s The roman numeral string
* @return The arabic integer value
*/
public final static int toInt(String s) throws NumberFormatException {
if (s == null || s.length() == 0) {
throw new NumberFormatException("Invalid roman numeral: a non-empty and non-null value must be given");
}
int i = 0;
int iconsecutive = 0; // number of consecutive same digits
int pos = 0;
int sum = 0;
RomanDigit prevDigit = null;
while (pos < s.length()) {
RomanDigit d = mapRoman.get(i);
if (!s.startsWith(mapRoman.get(i).numeral, pos)) {
i++;
// this is the only place we advance which digit we are checking,
// so if it exhausts the digits, then there is clearly a digit sequencing error or invalid digit
if (i == mapRoman.size()) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: invalid sequence '%s' following digit '%s'",
pos, s.substring(pos), prevDigit != null ? prevDigit.numeral : ""));
}
iconsecutive = 0;
continue;
}
// we now have the match for the next roman numeral digit to check
iconsecutive++;
if (iconsecutive > d.maxConsecutive) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: more than %d consecutive occurences of digit '%s'",
pos, d.maxConsecutive, d.numeral));
}
// invalid to encounter a higher digit sequence than the previous digit expects to have follow it
// (any digit is valid to start a roman numeral - i.e. when prevDigit == null)
if (prevDigit != null && prevDigit.maxNextValue < d.value) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: '%s' cannot follow '%s'",
pos, d.numeral, prevDigit.numeral));
}
// good to sum
sum += d.value;
if (sum > MAX_ARABIC) {
throw new NumberFormatException(
String.format("Invalid roman numeral at pos %d: adding '%s' exceeds the max value of %d",
pos, d.numeral, MAX_ARABIC));
}
pos += d.numeral.length();
prevDigit = d;
}
return sum;
}
}
Main.java
public class Main {
public static void main(String[] args) {
System.out.println("TEST arabic integer => roman numeral string");
for (int i = 0; i<= 4000; i++) {
String s;
try {
s = RomanNumeral.toRoman(i);
}
catch(NumberFormatException ex) {
s = ex.getMessage();
}
System.out.println(i + "\t =\t " + s);
}
System.out.println("TEST roman numeral string => arabic integer");
for (int i = 0; i<= 4000; i++) {
String s;
String msg;
try {
s = RomanNumeral.toRoman(i);
int n = testToInt(s);
assert(i == n); // ensure it is reflexively converting
}
catch (NumberFormatException ex) {
System.out.println(ex.getMessage() + "\t =\t toInt() skipped");
}
}
testToInt("MMMM");
testToInt("XCX");
testToInt("CDC");
testToInt("IVI");
testToInt("XXC");
testToInt("CCD");
testToInt("MDD");
testToInt("DD");
testToInt("CLL");
testToInt("LL");
testToInt("IIX");
testToInt("IVX");
testToInt("IIXX");
testToInt("XCIX");
testToInt("XIWE");
// Check validity via a regexp for laughs
String s = "IX";
System.out.println(s + " validity is " + s.matches("M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})"));
}
private final static int testToInt(String s) {
String msg;
int n=0;
try {
n = RomanNumeral.toInt(s);
msg = Integer.toString(n);
}
catch(NullPointerException | NumberFormatException ex) {
msg = ex.getMessage();
}
System.out.println(s + "\t =\t " + msg);
return n;
}
}
输出
TEST arabic integer => roman numeral string
0 = Invalid arabic value: 0, must be > 0 and < 3999
1 = I
2 = II
3 = III
4 = IV
5 = V
6 = VI
7 = VII
8 = VIII
9 = IX
10 = X
... [snip] ...
3988 = MMMCMLXXXVIII
3989 = MMMCMLXXXIX
3990 = MMMCMXC
3991 = MMMCMXCI
3992 = MMMCMXCII
3993 = MMMCMXCIII
3994 = MMMCMXCIV
3995 = MMMCMXCV
3996 = MMMCMXCVI
3997 = MMMCMXCVII
3998 = MMMCMXCVIII
3999 = MMMCMXCIX
4000 = Invalid arabic value: 4000, must be > 0 and < 3999
TEST roman numeral string => arabic integer
Invalid arabic value: 0, must be > 0 and < 3999 = toInt() skipped
I = 1
II = 2
III = 3
IV = 4
V = 5
VI = 6
VII = 7
VIII = 8
IX = 9
X = 10
... [snip] ...
MMMCMLXXXVIII = 3988
MMMCMLXXXIX = 3989
MMMCMXC = 3990
MMMCMXCI = 3991
MMMCMXCII = 3992
MMMCMXCIII = 3993
MMMCMXCIV = 3994
MMMCMXCV = 3995
MMMCMXCVI = 3996
MMMCMXCVII = 3997
MMMCMXCVIII = 3998
MMMCMXCIX = 3999
Invalid arabic value: 4000, must be > 0 and < 3999 = toInt() skipped
MMMM = Invalid roman numeral at pos 3: more than 3 consecutive occurences of digit 'M'
XCX = Invalid roman numeral at pos 2: 'X' cannot follow 'XC'
CDC = Invalid roman numeral at pos 2: 'C' cannot follow 'CD'
IVI = Invalid roman numeral at pos 2: 'I' cannot follow 'IV'
XXC = Invalid roman numeral at pos 2: invalid sequence 'C' following digit 'X'
CCD = Invalid roman numeral at pos 2: invalid sequence 'D' following digit 'C'
MDD = Invalid roman numeral at pos 2: more than 1 consecutive occurences of digit 'D'
DD = Invalid roman numeral at pos 1: more than 1 consecutive occurences of digit 'D'
CLL = Invalid roman numeral at pos 2: more than 1 consecutive occurences of digit 'L'
LL = Invalid roman numeral at pos 1: more than 1 consecutive occurences of digit 'L'
IIX = Invalid roman numeral at pos 2: invalid sequence 'X' following digit 'I'
IVX = Invalid roman numeral at pos 2: invalid sequence 'X' following digit 'IV'
IIXX = Invalid roman numeral at pos 2: invalid sequence 'XX' following digit 'I'
XCIX = 99
XIWE = Invalid roman numeral at pos 2: invalid sequence 'WE' following digit 'I'
IX validity is true
答案 10 :(得分:1)
让我们用3种不同的场景来看待这个问题
情景1:
当我们看到如下图案时
'IIIIII' or 'XXXXX' or 'CCCC'
其中所有字符都相同:我们在模式中添加每个字符的值
'IIIIII' gives us '6'
'XXXXX' gives us '50'
'CCCC' gives us '400'
情景2:
当我们看到任何2个连续字符不同时,其中第一个值的值小于第二个
'IX' or 'XC'
我们从第二个中减去第一个值。
second:'X' gives us '10'
first: 'I' gives us '1'
second - first : 10 - 1 = 9
情景3:
当我们看到任何2个连续字符不同时,第一个值大于第二个
'XI' or 'CX'
我们添加第一个和第二个例如
second:'I' gives us '10'
first: 'X' gives us '1'
first + second : 10 + 1 = 11
现在我们可以找到结果,如果我们递归地执行此操作。 这是java实现:
//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'];
}
答案 11 :(得分:0)
public static int convertFromRoman(String romanNumeral)
{
Character[] rnChars = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
int[] rnVals = { 1000, 500, 100, 50, 10, 5, 1 };
HashMap<Character, Integer> valueLookup = new HashMap<Character, Integer>();
for (int i = 0; i < rnChars.length;i++)
valueLookup.put(rnChars[i], rnVals[i]);
int retVal = 0;
for (int i = 0; i < romanNumeral.length();i++)
{
int addVal = valueLookup.get(romanNumeral.charAt(i));
retVal += i < romanNumeral.length()-1 &&
addVal < valueLookup.get(romanNumeral.charAt(i+1))?
-addVal:addVal;
}
return retVal;
}
答案 12 :(得分:0)
输入范围从1到3999的简便解决方案。
private static final Map<String, Integer> MAPPING = new HashMap<>() {{
put("I", 1);
put("V", 5);
put("X", 10);
put("L", 50);
put("C", 100);
put("D", 500);
put("M", 1000);
put("IV", 4);
put("IX", 9);
put("XL", 40);
put("XC", 90);
put("CD", 400);
put("CM", 900);
}};
public static int romanToInt(String s) {
int sum = 0;
for (int i = 0; i < s.length(); i++) {
if (i < s.length() - 1 && MAPPING.containsKey(String.valueOf(s.charAt(i)) + s.charAt(i + 1))) {
sum += MAPPING.get(String.valueOf(s.charAt(i)) + s.charAt(i + 1));
i++;
} else {
sum += MAPPING.get(String.valueOf(s.charAt(i)));
}
}
return sum;
}
答案 13 :(得分:0)
只有两个if语句: 优先检查第一个字符的匹配情况,如果不匹配,则匹配单个第一个字符。
public class Solution {
private static TreeMap<String, Integer> numeralsAndVal;
static{
numeralsAndVal = new TreeMap<>();
numeralsAndVal.put("M", 1000);
numeralsAndVal.put("CM", 900);
numeralsAndVal.put("D", 500);
numeralsAndVal.put("CD", 400);
numeralsAndVal.put("C", 100);
numeralsAndVal.put("XC", 90);
numeralsAndVal.put("L", 50);
numeralsAndVal.put("XL", 40);
numeralsAndVal.put("X", 10);
numeralsAndVal.put("IX", 9);
numeralsAndVal.put("V", 5);
numeralsAndVal.put("IV", 4);
numeralsAndVal.put("I", 1);
}
public int romanToInt(String A) {
if (A.length() == 0) return 0;
if (A.length() >= 2 && numeralsAndVal.containsKey(A.substring(0, 2))){
return numeralsAndVal.get(A.substring(0, 2)) + romanToInt(A.substring(2));
}
return numeralsAndVal.get(A.substring(0, 1)) + romanToInt(A.substring(1));
}
}
答案 14 :(得分:0)
使用尾递归的解决方案:
import java.util.LinkedHashMap;
public class RomanNumber {
private final static LinkedHashMap<String, Integer> roman2number = new LinkedHashMap<>(); // preserve key order
static {
roman2number.put("M", 1000);
roman2number.put("CM", 900);
roman2number.put("D", 500);
roman2number.put("CD", 400);
roman2number.put("C", 100);
roman2number.put("XC", 90);
roman2number.put("L", 50);
roman2number.put("XL", 40);
roman2number.put("X", 10);
roman2number.put("IX", 9);
roman2number.put("V", 5);
roman2number.put("IV", 4);
roman2number.put("I", 1);
}
public final static Integer toDecimal(String roman) {
for (String key : roman2number.keySet()) {
if (roman.startsWith(key)) {
if (roman.equals(key)) {
return roman2number.get(key);
}
return roman2number.get(key) + toDecimal(roman.substring(key.length()));
}
}
return 0;
}
}
测试:
import junitparams.JUnitParamsRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import junitparams.Parameters;
import static org.junit.Assert.assertTrue;
@RunWith(JUnitParamsRunner.class)
public class RomanNumberTest {
@Test
@Parameters({ "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", "50|L", "53|LIII", "57|LVII", "40|XL", "49|XLIX", "59|LIX", "79|LXXIX", "100|C", "90|XC", "99|XCIX",
"200|CC", "500|D", "499|CDXCIX", "999|CMXCIX", "2999|MMCMXCIX", "3999|MMMCMXCIX"
})
public void forRomanReturnsNumber(int number, String roman) {
assertTrue(roman + "->" + number, RomanNumber.toDecimal(roman) == (number));
}
}
答案 15 :(得分:0)
此scala
解决方案可能很有用:
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))
}
}
答案 16 :(得分:0)
public class RomanNumeral {
private final Map<Integer, String> arabicToRoman = new LinkedHashMap<Integer, String>();
private final Map<String, Integer> romanToArabic = new LinkedHashMap<String, Integer>();
public RomanNumeral() {
arabicToRoman.put(10, "X");
arabicToRoman.put(9, "IX");
arabicToRoman.put(5, "V");
arabicToRoman.put(4, "IV");
arabicToRoman.put(1, "I");
romanToArabic.put("X", 10);
romanToArabic.put("V", 5);
romanToArabic.put("I", 1);
}
public String convertToRomanNumeral(int number) {
String result = "";
for (Integer i : arabicToRoman.keySet()) {
while (number >= i) {
result += arabicToRoman.get(i);
number -= i;
}
}
return result;
}
public String convertToArabicNumber(String romanNumeral) {
int result = 0;
int top = 0;
for (int i = romanNumeral.length() - 1; i >= 0; i--) {
char current = romanNumeral.charAt(i);
int value = romanToArabic.get("" + current);
if (value < top) {
result -= value;
} else {
result += value;
top = value;
}
}
return "" + result;
}
}
答案 17 :(得分:0)
This is a modest variation of the recursive algorithm suggested by Sahtiel:
public static int toArabic(String number) throws Exception {
String[] letras = {"M","CM","D","CD","C","XC","L","XL","X", "IX","V","IV","I"};
int[] valores = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
// here we can do even more business validations like avoiding sequences like XXXXM
if (number==null || number.isEmpty()) {
return 0;
}
for(int i=0; i<letras.length; i++) {
if (number.startsWith(letras[i])) {
return valores[i] + toArabic(number.substring(letras[i].length()));
}
}
throw new Exception("something bad happened");
}
It uses less than 10 effective lines of code.
答案 18 :(得分:0)
我发现以下方法非常直观:
public void makeArray(String romanNumeral){
int[] numberArray = new int[romanNumeral.length()];
for(int i=0; i<romanNumeral.length();i++){
char symbol = romanNumeral.charAt(i);
switch(symbol){
case 'I':
numberArray[i] = 1;
break;
case 'V':
numberArray[i] = 5;
break;
case 'X':
numberArray[i] = 10;
break;
case 'L':
numberArray[i] = 50;
break;
case 'C':
numberArray[i] = 100;
break;
case 'D':
numberArray[i] = 500;
break;
case 'M':
numberArray[i] = 1000;
break;
}
}
calculate(numberArray);
}
public static void calculate(int[] numberArray){
int theNumber = 0;
for(int n=0;n<numberArray.length;n++){
if(n !=numberArray.length-1 && numberArray[n] < numberArray[n+1]){
numberArray[n+1] = numberArray[n+1] - numberArray[n];
numberArray[n] = 0;
}
}
for(int num:numberArray){
theNumber += num;
}
System.out.println("Converted number: " + theNumber);
}
答案 19 :(得分:0)
这是您对所有测试用例的要求和工作的非常基本的实现。如果你发现它有什么不对的话,我会尝试使其正确,代码也是用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;
}
答案 20 :(得分:0)
这个怎么样?
int getdec(const string& input)
{
int sum=0; char prev='%';
for(int i=(input.length()-1); i>=0; i--)
{
if(value(input[i])<sum && (input[i]!=prev))
{ sum -= value(input[i]);
prev = input[i];
}
else
{
sum += value(input[i]);
prev = input[i];
}
}
return sum;
}
答案 21 :(得分:0)
假设格式良好的罗马数字:
private static int totalValue(String val)
{
String aux=val.toUpperCase();
int sum=0, max=aux.length(), i=0;
while(i<max)
{
if ((i+1)<max && valueOf(aux.charAt(i+1))>valueOf(aux.charAt(i)))
{
sum+=valueOf(aux.charAt(i+1)) - valueOf(aux.charAt(i));
i+=2;
}
else
{
sum+=valueOf(aux.charAt(i));
i+=1;
}
}
return sum;
}
private static int valueOf(Character c)
{
char aux = Character.toUpperCase(c);
switch(aux)
{
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
default:
return 0;
}
}
答案 22 :(得分:0)
这次转换怎么样?没有开关,根本没有任何情况......
P.S。 :我在bash shell中使用这个脚本
import sys
def RomanToNum(r):
return {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
}[r]
#
#
#
EOF = "<"
Roman = sys.argv[1].upper().strip()+EOF
num = 0
i = 0
while True:
this = Roman[i]
if this == EOF:
break
n1 = RomanToNum(this)
next = Roman[i+1]
if next == EOF:
n2 = 0
else:
n2 = RomanToNum(next)
if n1 < n2:
n1 = -1 * n1
num = num + n1
i = i + 1
print num
答案 23 :(得分:0)
public class RomInt {
String roman;
int val;
void assign(String k)
{
roman=k;
}
private class Literal
{
public char literal;
public int value;
public Literal(char literal, int value)
{
this.literal = literal;
this.value = value;
}
}
private final Literal[] ROMAN_LITERALS = new Literal[]
{
new Literal('I', 1),
new Literal('V', 5),
new Literal('X', 10),
new Literal('L', 50),
new Literal('C', 100),
new Literal('D', 500),
new Literal('M', 1000)
};
public int getVal(String s) {
int holdValue=0;
for (int j = 0; j < ROMAN_LITERALS.length; j++)
{
if (s.charAt(0)==ROMAN_LITERALS[j].literal)
{
holdValue=ROMAN_LITERALS[j].value;
break;
} //if()
}//for()
return holdValue;
} //getVal()
public int count()
{
int count=0;
int countA=0;
int countB=0;
int lastPosition = 0;
for(int i = 0 ; i < roman.length(); i++)
{
String s1 = roman.substring(i,i+1);
int a=getVal(s1);
countA+=a;
}
for(int j=1;j<roman.length();j++)
{
String s2= roman.substring(j,j+1);
String s3= roman.substring(j-1,j);
int b=getVal(s2);
int c=getVal(s3);
if(b>c)
{
countB+=c;
}
}
count=countA-(2*countB);
return count;
}
void disp()
{
int result=count();
System.out.println("Integer equivalent of "+roman+" = " +result);
}
} //RomInt---BLC
答案 24 :(得分:0)
由于这里的大多数答案都是用Java编写的,我用C ++发布答案(因为我现在感到很无聊而且没有什么比这更有效率了)但请注意,除非代码错误,否则没有downvotes。 已知问题=不会处理溢出
代码:
#include <unordered_map>
int convert_roman_2_int(string& str)
{
int ans = 0;
if( str.length() == 0 )
{
return ans;
}
std::unordered_map<char, int> table;
table['I'] = 1;
table['V'] = 5;
table['X'] = 10;
table['L'] = 50;
table['C'] = 100;
table['D'] = 500;
table['M'] = 1000;
ans = table[ str[ str.length() - 1 ] ];
for( int i = str.length() - 2; i >= 0; i--)
{
if(table[ str[i] ] < table[ str[i+1] ] )
{
ans -= table[ str[i] ];
}
else
{
ans += table[ str[i] ];
}
}
return ans;
}
//测试代码
void run_test_cases_convert_roman_to_int()
{
string roman = "VIII";
int r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "XX";
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "CDX"; //410
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "MCMXC"; //1990
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "MMVIII"; //2008
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
roman = "MDCLXVI"; //1666
r = convert_roman_2_int(roman);
cout << roman << " in int is " << r << endl << flush;
}
答案 25 :(得分:0)
这应该有效:
import java.io.*;
import java.util.Scanner;
enum RomanToNumber {
i(1), v(5), x(10), l(50), c(100); int value;
RomanToNumber (int p){value = p;}
int getValue(){return value;}
}
public class RomanToInteger {
public static void main(String[] args){
RomanToNumber n;
System.out.println( "Type a valid roman number in lower case" );
String Str = new String(new Scanner(System.in).nextLine());
int n1 = 0, theNo = 0, len = Str.length();
int[] str2No = new int [len];
for(int i=0; i < len; i++){
n = RomanToNumber.valueOf(Str.substring(n1, ++n1));
str2No[i] = n.getValue();
}
for(int j = 0; j < (len-1); j++){
if( str2No[j] >= str2No[j+1] ){ theNo += str2No[j]; }
else{ theNo -= str2No[j]; }
}
System.out.println( theNo += str2No[len-1] );
}
}
答案 26 :(得分:0)
刚开始使用Java,很棒的工作。
public int getDecimal (String roman) {
int decimal = 0;
int romanNumber = 0;
int prev = 0;
for (int i = roman.length()-1; i >= 0; i--){
romanNumber = hashRomans.get(roman.charAt(i));
if(romanNumber < decimal && romanNumber != prev ){
decimal -= romanNumber;
prev = romanNumber;
} else {
decimal += romanNumber;
prev = romanNumber;
}
}
return decimal;
}
答案 27 :(得分:0)
//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);
}
}
答案 28 :(得分:-1)
这是我的......
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;
}
}