将整数转换为罗马数字 – Java

这是我有麻烦的作业。

我需要一个整数罗马数字转换器使用一种方法。 之后,我必须用这个程序用罗马数字写出1到3999,所以硬编码就出来了。 我的下面的代码是非常简单的; 它是一个基本的I / O循环,在我们在课堂上使用getIntegerFromUser的包的getIntegerFromUser退出。

有没有办法给string赋值,然后在我调用方法时将它们加在一起?

更新:我从我的教授那里得到一些伪代码来帮助我,而当我明白他想说什么时,我在if遇到了一些麻烦。 我是否需要很多很多if语句,以便我的转换器能够正确处理罗马数字格式,或者是否有办法以更高的效率进行处理? 我更新了我的代码以反映我的占位符方法。

更新(2012年10月28日):我得到了它的工作。 这是我最终使用的:

 public static String IntegerToRomanNumeral(int input) { if (input < 1 || input > 3999) return "Invalid Roman Number Value"; String s = ""; while (input >= 1000) { s += "M"; input -= 1000; } while (input >= 900) { s += "CM"; input -= 900; } while (input >= 500) { s += "D"; input -= 500; } while (input >= 400) { s += "CD"; input -= 400; } while (input >= 100) { s += "C"; input -= 100; } while (input >= 90) { s += "XC"; input -= 90; } while (input >= 50) { s += "L"; input -= 50; } while (input >= 40) { s += "XL"; input -= 40; } while (input >= 10) { s += "X"; input -= 10; } while (input >= 9) { s += "IX"; input -= 9; } while (input >= 5) { s += "V"; input -= 5; } while (input >= 4) { s += "IV"; input -= 4; } while (input >= 1) { s += "I"; input -= 1; } return s; } 

使用Java TreeMap和recursion的紧凑实现:

 import java.util.TreeMap; public class RomanNumber { private final static TreeMap<Integer, String> map = new TreeMap<Integer, String>(); static { map.put(1000, "M"); map.put(900, "CM"); map.put(500, "D"); map.put(400, "CD"); map.put(100, "C"); map.put(90, "XC"); map.put(50, "L"); map.put(40, "XL"); map.put(10, "X"); map.put(9, "IX"); map.put(5, "V"); map.put(4, "IV"); map.put(1, "I"); } public final static String toRoman(int number) { int l = map.floorKey(number); if ( number == l ) { return map.get(number); } return map.get(l) + toRoman(number-l); } } 

testing:

 public void testRomanConversion() { for (int i = 1; i<= 100; i++) { System.out.println(i+"\t =\t "+RomanNumber.toRoman(i)); } } 

这是我的答案:

使用这些库:

 import java.util.LinkedHashMap; import java.util.Map; 

代码:

  public static String RomanNumerals(int Int) { LinkedHashMap<String, Integer> roman_numerals = new LinkedHashMap<String, Integer>(); roman_numerals.put("M", 1000); roman_numerals.put("CM", 900); roman_numerals.put("D", 500); roman_numerals.put("CD", 400); roman_numerals.put("C", 100); roman_numerals.put("XC", 90); roman_numerals.put("L", 50); roman_numerals.put("XL", 40); roman_numerals.put("X", 10); roman_numerals.put("IX", 9); roman_numerals.put("V", 5); roman_numerals.put("IV", 4); roman_numerals.put("I", 1); String res = ""; for(Map.Entry<String, Integer> entry : roman_numerals.entrySet()){ int matches = Int/entry.getValue(); res += repeat(entry.getKey(), matches); Int = Int % entry.getValue(); } return res; } public static String repeat(String s, int n) { if(s == null) { return null; } final StringBuilder sb = new StringBuilder(); for(int i = 0; i < n; i++) { sb.append(s); } return sb.toString(); } 

testing代码:

  for (int i = 1;i<256;i++) { System.out.println("i="+i+" -> "+RomanNumerals(i)); } 

输出:

  i=1 -> I i=2 -> II i=3 -> III i=4 -> IV i=5 -> V i=6 -> VI i=7 -> VII i=8 -> VIII i=9 -> IX i=10 -> X i=11 -> XI i=12 -> XII i=13 -> XIII i=14 -> XIV i=15 -> XV i=16 -> XVI i=17 -> XVII i=18 -> XVIII i=19 -> XIX i=20 -> XX i=21 -> XXI i=22 -> XXII i=23 -> XXIII i=24 -> XXIV i=25 -> XXV i=26 -> XXVI i=27 -> XXVII i=28 -> XXVIII i=29 -> XXIX i=30 -> XXX i=31 -> XXXI i=32 -> XXXII i=33 -> XXXIII i=34 -> XXXIV i=35 -> XXXV i=36 -> XXXVI i=37 -> XXXVII i=38 -> XXXVIII i=39 -> XXXIX i=40 -> XL i=41 -> XLI i=42 -> XLII i=43 -> XLIII i=44 -> XLIV i=45 -> XLV i=46 -> XLVI i=47 -> XLVII i=48 -> XLVIII i=49 -> XLIX i=50 -> L i=51 -> LI i=52 -> LII i=53 -> LIII i=54 -> LIV i=55 -> LV i=56 -> LVI i=57 -> LVII i=58 -> LVIII i=59 -> LIX i=60 -> LX i=61 -> LXI i=62 -> LXII i=63 -> LXIII i=64 -> LXIV i=65 -> LXV i=66 -> LXVI i=67 -> LXVII i=68 -> LXVIII i=69 -> LXIX i=70 -> LXX i=71 -> LXXI i=72 -> LXXII i=73 -> LXXIII i=74 -> LXXIV i=75 -> LXXV i=76 -> LXXVI i=77 -> LXXVII i=78 -> LXXVIII i=79 -> LXXIX i=80 -> LXXX i=81 -> LXXXI i=82 -> LXXXII i=83 -> LXXXIII i=84 -> LXXXIV i=85 -> LXXXV i=86 -> LXXXVI i=87 -> LXXXVII i=88 -> LXXXVIII i=89 -> LXXXIX i=90 -> XC i=91 -> XCI i=92 -> XCII i=93 -> XCIII i=94 -> XCIV i=95 -> XCV i=96 -> XCVI i=97 -> XCVII i=98 -> XCVIII i=99 -> XCIX i=100 -> C i=101 -> CI i=102 -> CII i=103 -> CIII i=104 -> CIV i=105 -> CV i=106 -> CVI i=107 -> CVII i=108 -> CVIII i=109 -> CIX i=110 -> CX i=111 -> CXI i=112 -> CXII i=113 -> CXIII i=114 -> CXIV i=115 -> CXV i=116 -> CXVI i=117 -> CXVII i=118 -> CXVIII i=119 -> CXIX i=120 -> CXX i=121 -> CXXI i=122 -> CXXII i=123 -> CXXIII i=124 -> CXXIV i=125 -> CXXV i=126 -> CXXVI i=127 -> CXXVII i=128 -> CXXVIII i=129 -> CXXIX i=130 -> CXXX i=131 -> CXXXI i=132 -> CXXXII i=133 -> CXXXIII i=134 -> CXXXIV i=135 -> CXXXV i=136 -> CXXXVI i=137 -> CXXXVII i=138 -> CXXXVIII i=139 -> CXXXIX i=140 -> CXL i=141 -> CXLI i=142 -> CXLII i=143 -> CXLIII i=144 -> CXLIV i=145 -> CXLV i=146 -> CXLVI i=147 -> CXLVII i=148 -> CXLVIII i=149 -> CXLIX i=150 -> CL i=151 -> CLI i=152 -> CLII i=153 -> CLIII i=154 -> CLIV i=155 -> CLV i=156 -> CLVI i=157 -> CLVII i=158 -> CLVIII i=159 -> CLIX i=160 -> CLX i=161 -> CLXI i=162 -> CLXII i=163 -> CLXIII i=164 -> CLXIV i=165 -> CLXV i=166 -> CLXVI i=167 -> CLXVII i=168 -> CLXVIII i=169 -> CLXIX i=170 -> CLXX i=171 -> CLXXI i=172 -> CLXXII i=173 -> CLXXIII i=174 -> CLXXIV i=175 -> CLXXV i=176 -> CLXXVI i=177 -> CLXXVII i=178 -> CLXXVIII i=179 -> CLXXIX i=180 -> CLXXX i=181 -> CLXXXI i=182 -> CLXXXII i=183 -> CLXXXIII i=184 -> CLXXXIV i=185 -> CLXXXV i=186 -> CLXXXVI i=187 -> CLXXXVII i=188 -> CLXXXVIII i=189 -> CLXXXIX i=190 -> CXC i=191 -> CXCI i=192 -> CXCII i=193 -> CXCIII i=194 -> CXCIV i=195 -> CXCV i=196 -> CXCVI i=197 -> CXCVII i=198 -> CXCVIII i=199 -> CXCIX i=200 -> CC i=201 -> CCI i=202 -> CCII i=203 -> CCIII i=204 -> CCIV i=205 -> CCV i=206 -> CCVI i=207 -> CCVII i=208 -> CCVIII i=209 -> CCIX i=210 -> CCX i=211 -> CCXI i=212 -> CCXII i=213 -> CCXIII i=214 -> CCXIV i=215 -> CCXV i=216 -> CCXVI i=217 -> CCXVII i=218 -> CCXVIII i=219 -> CCXIX i=220 -> CCXX i=221 -> CCXXI i=222 -> CCXXII i=223 -> CCXXIII i=224 -> CCXXIV i=225 -> CCXXV i=226 -> CCXXVI i=227 -> CCXXVII i=228 -> CCXXVIII i=229 -> CCXXIX i=230 -> CCXXX i=231 -> CCXXXI i=232 -> CCXXXII i=233 -> CCXXXIII i=234 -> CCXXXIV i=235 -> CCXXXV i=236 -> CCXXXVI i=237 -> CCXXXVII i=238 -> CCXXXVIII i=239 -> CCXXXIX i=240 -> CCXL i=241 -> CCXLI i=242 -> CCXLII i=243 -> CCXLIII i=244 -> CCXLIV i=245 -> CCXLV i=246 -> CCXLVI i=247 -> CCXLVII i=248 -> CCXLVIII i=249 -> CCXLIX i=250 -> CCL i=251 -> CCLI i=252 -> CCLII i=253 -> CCLIII i=254 -> CCLIV i=255 -> CCLV 

从Java Notes 6.0网站:

  /** * An object of type RomanNumeral is an integer between 1 and 3999. It can * be constructed either from an integer or from a string that represents * a Roman numeral in this range. The function toString() will return a * standardized Roman numeral representation of the number. The function * toInt() will return the number as a value of type int. */ public class RomanNumeral { private final int num; // The number represented by this Roman numeral. /* The following arrays are used by the toString() function to construct the standard Roman numeral representation of the number. For each i, the number numbers[i] is represented by the corresponding string, letters[i]. */ private static int[] numbers = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; private static String[] letters = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; /** * Constructor. Creates the Roman number with the int value specified * by the parameter. Throws a NumberFormatException if arabic is * not in the range 1 to 3999 inclusive. */ public RomanNumeral(int arabic) { if (arabic < 1) throw new NumberFormatException("Value of RomanNumeral must be positive."); if (arabic > 3999) throw new NumberFormatException("Value of RomanNumeral must be 3999 or less."); num = arabic; } /* * Constructor. Creates the Roman number with the given representation. * For example, RomanNumeral("xvii") is 17. If the parameter is not a * legal Roman numeral, a NumberFormatException is thrown. Both upper and * lower case letters are allowed. */ public RomanNumeral(String roman) { if (roman.length() == 0) throw new NumberFormatException("An empty string does not define a Roman numeral."); roman = roman.toUpperCase(); // Convert to upper case letters. int i = 0; // A position in the string, roman; int arabic = 0; // Arabic numeral equivalent of the part of the string that has // been converted so far. while (i < roman.length()) { char letter = roman.charAt(i); // Letter at current position in string. int number = letterToNumber(letter); // Numerical equivalent of letter. i++; // Move on to next position in the string if (i == roman.length()) { // There is no letter in the string following the one we have just processed. // So just add the number corresponding to the single letter to arabic. arabic += number; } else { // Look at the next letter in the string. If it has a larger Roman numeral // equivalent than number, then the two letters are counted together as // a Roman numeral with value (nextNumber - number). int nextNumber = letterToNumber(roman.charAt(i)); if (nextNumber > number) { // Combine the two letters to get one value, and move on to next position in string. arabic += (nextNumber - number); i++; } else { // Don't combine the letters. Just add the value of the one letter onto the number. arabic += number; } } } // end while if (arabic > 3999) throw new NumberFormatException("Roman numeral must have value 3999 or less."); num = arabic; } // end constructor /** * Find the integer value of letter considered as a Roman numeral. Throws * NumberFormatException if letter is not a legal Roman numeral. The letter * must be upper case. */ private int letterToNumber(char letter) { switch (letter) { 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: throw new NumberFormatException( "Illegal character \"" + letter + "\" in Roman numeral"); } } /** * Return the standard representation of this Roman numeral. */ public String toString() { String roman = ""; // The roman numeral. int N = num; // N represents the part of num that still has // to be converted to Roman numeral representation. for (int i = 0; i < numbers.length; i++) { while (N >= numbers[i]) { roman += letters[i]; N -= numbers[i]; } } return roman; } /** * Return the value of this Roman numeral as an int. */ public int toInt() { return num; } } 

实际上,还有另外一种看待这个问题的方法,不是一个数字问题,而是一个一元问题,从罗马数字的基本字符“I”开始。 所以我们用I来表示数字,然后我们用罗马字符的升序来replace字符。

 public String getRomanNumber(int number) { return join("", nCopies(number, "I")) .replace("IIIII", "V") .replace("IIII", "IV") .replace("VV", "X") .replace("VIV", "IX") .replace("XXXXX", "L") .replace("XXXX", "XL") .replace("LL", "C") .replace("LXL", "XC") .replace("CCCCC", "D") .replace("CCCC", "CD") .replace("DD", "M") .replace("DCD", "CM"); } 

我特别喜欢这种解决这个问题的方法,而不是使用大量的if和while循环,或者查找表。 当你把这个问题看作一个数字问题的时候,它实际上也是一个戒烟直觉的解决scheme。

我写了一个非常简单的解决scheme。 我们所要做的就是划分和查找一个特定的字母(或字母组合)发生了多less次,然后将其附加到StringBuilder对象sb 。 我们也应该跟踪剩余的数字( num )。

 public static String intToRoman(int num) { StringBuilder sb = new StringBuilder(); int times = 0; String[] romans = new String[] { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M" }; int[] ints = new int[] { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; for (int i = ints.length - 1; i >= 0; i--) { times = num / ints[i]; num %= ints[i]; while (times > 0) { sb.append(romans[i]); times--; } } return sb.toString(); } 

我认为我的解决scheme是一个更简洁的:

 private static String convertToRoman(int mInt) { String[] rnChars = { "M", "CM", "D", "C", "XC", "L", "X", "IX", "V", "I" }; int[] rnVals = { 1000, 900, 500, 100, 90, 50, 10, 9, 5, 1 }; String retVal = ""; for (int i = 0; i < rnVals.length; i++) { int numberInPlace = mInt / rnVals[i]; if (numberInPlace == 0) continue; retVal += numberInPlace == 4 && i > 0? rnChars[i] + rnChars[i - 1]: new String(new char[numberInPlace]).replace("\0",rnChars[i]); mInt = mInt % rnVals[i]; } return retVal; } 

我喜欢AndréKramer Orten的回答,非常优雅,我特别喜欢它如何避免循环,我想另一种方式来处理它也避免循环。

它使用整数除法和模从每个单元types的硬编码string数组中select正确的索引。

这里的好处是你可以指定确切的转换,取决于你是否需要添加或实质性的数字forms,即IIII对IV。 在这里,我使用5x-1(4,9,14,19,40,90等)forms的所有数字的“减法forms”

通过简单地用更多的加法或减法forms(即“IV”,“V”或“MMMM”,“MMMMM”)扩展数千个arrays来扩展这个以允许更大数目也是微不足道的。

对于奖励积分,我实际上确保数字参数在问题的给定范围内。

 public class RomanNumeralGenerator { static final int MIN_VALUE = 1; static final int MAX_VALUE = 3999; static final String[] RN_M = {"", "M", "MM", "MMM"}; static final String[] RN_C = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; static final String[] RN_X = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; static final String[] RN_I = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; public String generate(int number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException( String.format( "The number must be in the range [%d, %d]", MIN_VALUE, MAX_VALUE ) ); } return new StringBuilder() .append(RN_M[number / 1000]) .append(RN_C[number % 1000 / 100]) .append(RN_X[number % 100 / 10]) .append(RN_I[number % 10]) .toString(); } } 
 String convert(int i){ String ones = ""; String tens = ""; String hundreds = ""; String thousands = ""; String result ; boolean error = false; Vector v = new Vector(); //assign passed integer to temporary value temp int temp=i; //flags an error if number is greater than 3999 if (temp >=4000) { error = true; } /*loops while temp can no more be divided by 10. Lets say i = 3254, then temp is also 3254 at line 14. 3254 3254/10 = 25 / \ 3254%10 = 4 / \ now temp = 25 325 4 - here 4 is added to the vector v's 0th index. / \ now temp = 32 32 5 - here 5 is added to the vector v's 1st index. / \ now temp = 3 3 2 - here 2 is added to the vector v's 2nd index, and loop exits / \ since temp/10 = 0 0 3 - here 3 is not added to the vector v's 3rd index as loop exits when temp/10 = 0. */ while (temp/10 != 0) { if (temp / 10 != 0 && temp <4000) { v.add(temp%10); temp = temp / 10; }else { break; } } //therefore you have to add temp one last time to the vector v.add(temp); //as in the example now you have 4,5,2,3 respectively in v's 0,1,2,3 indices. for (int j = 0; j < v.size(); j++) { //you see that v's 0th index has number of ones. So make them roman ones here. if (j==0) { switch (v.get(0).toString()){ case "0" : ones = ""; break; case "1" : ones = "I"; break; case "2" : ones = "II"; break; case "3" : ones = "III"; break; case "4" : ones = "IV"; break; case "5" : ones = "V"; break; case "6" : ones = "VI"; break; case "7" : ones = "VII"; break; case "8" : ones = "VIII"; break; case "9" : ones = "IX"; break; } //in the second iteration of the loop (when j==1) //index 1 of v is checked. Now you understand that v's 1st index //has the tens } else if (j == 1) { switch (v.get(1).toString()){ case "0" : tens = ""; break; case "1" : tens = "X"; break; case "2" : tens = "XX"; break; case "3" : tens = "XXX"; break; case "4" : tens = "XL"; break; case "5" : tens = "L"; break; case "6" : tens = "LX"; break; case "7" : tens = "LXX"; break; case "8" : tens = "LXXX"; break; case "9" : tens = "XC"; break; } } else if(j == 2){ //and hundreds switch (v.get(2).toString()){ case "0" : hundreds = ""; break; case "1" : hundreds = "C"; break; case "2" : hundreds = "CC"; break; case "3" : hundreds = "CCC"; break; case "4" : hundreds = "CD"; break; case "5" : hundreds = "D"; break; case "6" : hundreds = "DC"; break; case "7" : hundreds = "DCC"; break; case "8" : hundreds = "DCCC"; break; case "9" : hundreds = "CM"; break; } } else if(j == 3){ //and finally thousands. switch (v.get(3).toString()){ case "0" : thousands = ""; break; case "1" : thousands = "M"; break; case "2" : thousands = "MM"; break; case "3" : thousands = "MMM"; break; } } } if (error) { result = "Error!"; }else{ result = thousands + hundreds + tens + ones; } return result; } 

我很好奇这将如何结束。 我开始研究映射1,2,3,5,6,7,8,9,10到I,II,III,IV,V,VI,VII,VII,IX,X …然后你可能会查看罗马数字的规则:I,II,III由联合创buildV,X,L,C,D和M是5,10,50,100,500和1000的符号罗马人认为他们可以拯救写数字的空间,而不是写作,例如IIII 4使用IV(意思是:5减1 …)你可能想要看看这些规则,例如在http://en.wikipedia.org/wiki/Roman_numerals并捕获它们在代码中,例如在类“RomanNumbers”如果你想作弊,你可能想要按照链接http://www.moxlotus.alternatifs.eu/programmation-converter.html

我的解决scheme是在函数getRoman:

 public String getRoman(int number) { String riman[] = {"M","XM","CM","D","XD","CD","C","XC","L","XL","X","IX","V","IV","I"}; int arab[] = {1000, 990, 900, 500, 490, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; StringBuilder result = new StringBuilder(); int i = 0; while (number > 0 || arab.length == (i - 1)) { while ((number - arab[i]) >= 0) { number -= arab[i]; result.append(riman[i]); } i++; } return result.toString(); } 

我认为,如果你仔细研究罗马数字的理论,你不需要数字4,9,40等的映射,因为理论告诉我们,如果罗马数字是IV = 5-1 = 4,因此当前缀小于在这种情况下,你必须从后面的数字中减去前面的数字来获得实际的值,这就是我已经将这个问题编入我的代码中,如果有必要的话,请看一下并指出任何错误,我跟着这个表来devise我的逻辑 – http://literacy.kent.edu/Minigrants/Cinci/romanchart.htm

 import java.util.Set; import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.io.FileReader; import java.io.IOException; import java.io.BufferedReader; public class RomanStringToIntegerConversion { public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in))); String[] romanString = br.readLine().split(""); HashMap<String, Integer> romanToIntegerMap = new HashMap<String, Integer>(); romanToIntegerMap.put("I", 1); romanToIntegerMap.put("V", 5); romanToIntegerMap.put("X", 10); romanToIntegerMap.put("L", 50); romanToIntegerMap.put("C", 100); romanToIntegerMap.put("D", 500); romanToIntegerMap.put("M", 1000); int numLength = romanString.length; Set<Integer> lessIndices = new HashSet<Integer>(); for(int i = 0; i < numLength; ++i){ if(i+1 < numLength){ if(romanToIntegerMap.get(romanString[i]) < romanToIntegerMap.get(romanString[i+1])) lessIndices.add(i); } } int num = 0; for(int i = 0; i < numLength;){ if(!lessIndices.contains(i)){ num = num + romanToIntegerMap.get(romanString[i]); ++i; } else{ num = num + romanToIntegerMap.get(romanString[i+1]) - romanToIntegerMap.get(romanString[i]); i+=2; } } System.out.println("The integer representation of the roman numeral is : " + num); } } 

我注意到从整数转换成罗马数字是相当容易的,因为每个数字总是有1,5和10的数字(例如IVX代表1-10, XLC代表10-100等等)这就是为什么我做了一个罗马数字来从正确的信件。

在我的例子中,我每次都通过整数一位数字,每次都使用模运算符来获得最后一位数字。 然后,我从switch-statement中的当前数字形成罗马数字,并将其添加到asRomanNumerals String的开头。 在数字被翻译之后,它被从数字和索引中用来查找数组中的字母从数字和索引中移除,增加了两个( IVX – > XLC )。

 public static void main(String[] args) { // number is the one to be translated into Roman Numerals int number = 2345; number = Math.min(3999, Math.max(1, number)); // wraps number between 1-3999 String asRomanNumerals = ""; // Array including numerals in ascending order String[] RN = {"I", "V", "X", "L", "C", "D", "M" }; int i = 0; // Index used to keep track which digit we are translating while (number > 0) { switch(number % 10) { case 1: asRomanNumerals = RN[i] + asRomanNumerals; break; case 2: asRomanNumerals = RN[i] + RN[i] + asRomanNumerals; break; case 3: asRomanNumerals = RN[i] + RN[i] + RN[i] + asRomanNumerals; break; case 4: asRomanNumerals = RN[i] + RN[i + 1] + asRomanNumerals; break; case 5: asRomanNumerals = RN[i + 1] + asRomanNumerals; break; case 6: asRomanNumerals = RN[i + 1] + RN[i] + asRomanNumerals; break; case 7: asRomanNumerals = RN[i + 1] + RN[i] + RN[i] + asRomanNumerals; break; case 8: asRomanNumerals = RN[i + 1] + RN[i] + RN[i] + RN[i] +asRomanNumerals; break; case 9: asRomanNumerals = RN[i] + RN[i + 2] + asRomanNumerals; break; } number = (int) number / 10; i += 2; } System.out.println(asRomanNumerals); } 
 enum Numeral { I(1), IV(4), V(5), IX(9), X(10), XL(40), L(50), XC(90), C(100), CD(400), D(500), CM(900), M(1000); int weight; Numeral(int weight) { this.weight = weight; } }; public static String roman(long n) { if( n <= 0) { throw new IllegalArgumentException(); } StringBuilder buf = new StringBuilder(); final Numeral[] values = Numeral.values(); for (int i = values.length - 1; i >= 0; i--) { while (n >= values[i].weight) { buf.append(values[i]); n -= values[i].weight; } } return buf.toString(); } public static void test(long n) { System.out.println(n + " = " + roman(n)); } public static void main(String[] args) { test(1999); test(25); test(944); test(0); } 

这是我的家庭作业的结果。 它不能确保input是在正确的范围内,我可能应该使用StringBuilder (我查了起来!),并不是一个单一的方法。 但是,如果有人正在阅读这一点,我会欣赏它的积极和消极的反馈!

 import java.util.Scanner; /** *Main() allows user input and tests 1-3999 *toRoman() breaks the number down into digits and passes them to romanLogic() *romanLogic() converts each digit into a the numerals that represent it. */ public class RomanNumerals { public static void main(String args[]){ Scanner in = new Scanner(System.in); System.out.print("give us an integer < 4000: "); System.out.println("the roman numeral version is: " + toRoman(in.nextInt())); for (int i = 1; i<=3999; i++){ System.out.println(i +" === "+ toRoman(i)); } } public static String toRoman(int i){ String output = ""; int digits = i%10; int tens = (i%100)/10; int hundreds = (i%1000)/100; int thousands = (i%10000)/1000; return (romanLogic(thousands, "M","","")+ romanLogic(hundreds,"C","D","M")+ romanLogic(tens,"X","L","C")+ romanLogic(digits,"I","V","X")); } public static String romanLogic(int i, String ones, String fives, String tens){ String result = ""; if (i == 0){ return result; } else { if ((i>=4)&&(i<=8)){ result += fives; } if (i==9){ result += tens; } if(i%5 < 4){ while(i%5 > 0){ result += ones; i--; } } if(i%5 == 4){ result = ones + result; } } return result; } } 

这可能有助于:

 using System; using System.Text; public class Test { public static string ToRoman(int number) { StringBuilder br=new StringBuilder(""); while(number!=0) { if(number>=1000) { br.Append("M"); number-=1000; } if(number>=900) { br.Append("CM"); number-=900; } if(number>=500) { br.Append("D"); number-=500; } if(number>=400) { br.Append("CD"); number-=400; } if(number>=100) { br.Append("C"); number-=100; } if(number>=90) { br.Append("XC"); number-=90; } if(number>=50) { br.Append("L"); number-=50; } if(number>=40) { br.Append("XL"); number-=40; } if(number>=10) { br.Append("X"); number-=10; } if(number>=9) { br.Append("IX"); number-=9; } if(number>=5) { br.Append("V"); number-=5; } if(number>=4) { br.Append("IV"); number-=4; } if(number>=1) { br.Append("I"); number-=1; } } return br.ToString(); } public static void Main() { Console.WriteLine(ToRoman(int.Parse(Console.ReadLine()))); } } 

在看到一些答案后,我不得不发布这个。 我认为我的algorithm是最容易理解的,即使在相对较大的规模上,丢失的性能也不重要。 我也服从标准化的编码惯例,而不是这里的一些用户。

平均转换时间:0.05ms(基于将所有数字转换为1-3999并除以3999)

 public static String getRomanNumeral(int arabicNumber) { if (arabicNumber > 0 && arabicNumber < 4000) { final LinkedHashMap<Integer, String> numberLimits = new LinkedHashMap<>(); numberLimits.put(1, "I"); numberLimits.put(4, "IV"); numberLimits.put(5, "V"); numberLimits.put(9, "IX"); numberLimits.put(10, "X"); numberLimits.put(40, "XL"); numberLimits.put(50, "L"); numberLimits.put(90, "XC"); numberLimits.put(100, "C"); numberLimits.put(400, "CD"); numberLimits.put(500, "D"); numberLimits.put(900, "CM"); numberLimits.put(1000, "M"); String romanNumeral = ""; while (arabicNumber > 0) { int highestFound = 0; for (Map.Entry<Integer, String> current : numberLimits.entrySet()){ if (current.getKey() <= arabicNumber) { highestFound = current.getKey(); } } romanNumeral += numberLimits.get(highestFound); arabicNumber -= highestFound; } return romanNumeral; } else { throw new UnsupportedOperationException(arabicNumber + " is not a valid Roman numeral."); } } 

首先你必须考虑到罗马数字只在<1-4000的区间内,但是这可以通过一个简单的如果抛出的exception来解决。 然后,您可以尝试查找给定整数中最大的一组罗马数字,如果find,则从原始数字中减去它并将其添加到结果中。 重复新获得的号码,直到你达到零。

基于OP自己的解决scheme,通过使用enum替代解决scheme。 此外,还包括parsing器和往返testing。

 public class RomanNumber { public enum Digit { M(1000, 3), CM(900, 1), D(500, 1), CD(400, 1), C(100, 3), XC(90, 1), L(50, 1), XL(40, 1), X(10, 3), IX(9, 1), V(5, 1), IV(4, 1), I(1, 3); public final int value; public final String symbol = name(); public final int maxArity; private Digit(int value, int maxArity) { this.value = value; this.maxArity = maxArity; } } private static final Digit[] DIGITS = Digit.values(); public static String of(int number) { if (number < 1 || 3999 < number) { throw new IllegalArgumentException(String.format( "Roman numbers are only defined for numbers between 1 and 3999 (%d was given)", number )); } StringBuilder sb = new StringBuilder(); for (Digit digit : DIGITS) { int value = digit.value; String symbol = digit.symbol; while (number >= value) { sb.append(symbol); number -= value; } } return sb.toString(); } public static int parse(String roman) { if (roman.isEmpty()) { throw new NumberFormatException("The empty string does not comprise a valid Roman number"); } int number = 0; int offset = 0; for (Digit digit : DIGITS) { int value = digit.value; int maxArity = digit.maxArity; String symbol = digit.symbol; for (int i = 0; i < maxArity && roman.startsWith(symbol, offset); i++) { number += value; offset += symbol.length(); } } if (offset != roman.length()) { throw new NumberFormatException(String.format( "The string '%s' does not comprise a valid Roman number", roman )); } return number; } /** TESTS */ public static void main(String[] args) { /* Demonstrating round-trip for all possible inputs. */ for (int number = 1; number <= 3999; number++) { String roman = of(number); int parsed = parse(roman); if (parsed != number) { System.err.format( "ERROR: number: %d, roman: %s, parsed: %d\n", number, roman, parsed ); } } /* Some illegal inputs. */ int[] illegalNumbers = { -1, 0, 4000, 4001 }; for (int illegalNumber : illegalNumbers) { try { of(illegalNumber); System.err.format( "ERROR: Expected failure on number %d\n", illegalNumber ); } catch (IllegalArgumentException e) { // Failed as expected. } } String[] illegalRomans = { "MMMM", "CDCD", "IM", "T", "", "VV", "DM" }; for (String illegalRoman : illegalRomans) { try { parse(illegalRoman); System.err.format( "ERROR: Expected failure on roman %s\n", illegalRoman ); } catch (NumberFormatException e) { // Failed as expected. } } } } 

在做了一些研究和分析上面的答案后,我结束了这个:

 package roman; public class RomanNumbers { public static final int[] decimal = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000}; public static final String[] letters = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"}; public static String stringToRoman(int num) { String roman = ""; if (num < 1 || num > 3999) { System.out.println("Invalid roman number value!"); } while (num > 0) { int maxFound = 0; for (int i=0; i < decimal.length; i++) { if (num >= decimal[i]) { maxFound = i; } } roman += letters[maxFound]; num -= decimal[maxFound]; } return roman; } } 

Unit tests also passed:

 package roman; import static org.junit.Assert.*; import org.junit.Test; public class RomanNumbersTest { @Test public void testReturn1() { String actual = RomanNumbers.stringToRoman(1); String expected = "I"; assertEquals(expected, actual); } @Test public void testReturn5() { String actual = RomanNumbers.stringToRoman(5); String expected = "V"; assertEquals(expected, actual); } @Test public void testReturn2() { String actual = RomanNumbers.stringToRoman(2); String expected = "II"; assertEquals(expected, actual); } @Test public void testReturn4() { String actual = RomanNumbers.stringToRoman(4); String expected = "IV"; assertEquals(expected, actual); } @Test public void testReturn399() { String actual = RomanNumbers.stringToRoman(399); String expected = "CCCXCIX"; assertEquals(expected, actual); } @Test public void testReturn3992() { String actual = RomanNumbers.stringToRoman(3992); String expected = "MMMCMXCII"; assertEquals(expected, actual); } } 

最简单的解决scheme

 public class RomanNumerals { private static int [] arabic = {50, 40, 10, 9, 5, 4, 1}; private static String [] roman = {"L", "XL", "X", "IX", "V", "IV", "I"}; public static String convert(int arabicNumber) { StringBuilder romanNumerals = new StringBuilder(); int remainder = arabicNumber; for (int i=0;i<arabic.length;i++) { while (remainder >= arabic[i]) { romanNumerals.append(roman[i]); remainder -= arabic[i]; } } return romanNumerals.toString(); } } 
 private String convertToRoman(int num) { String result = ""; while(num > 0){ if(num >= 1000){ result += "M"; num -= 1000; }else if(num >= 900){ result += "CM"; num -= 900; } else if(num >= 500){ result += "D"; num -= 500; }else if(num >= 400){ result += "CD"; num -= 400; }else if(num >= 100){ result += "C"; num -= 100; }else if(num >= 90){ result += "XC"; num -= 90; }else if(num >= 50){ result += "L"; num -= 50; }else if(num >= 40){ result += "XL"; num -= 40; } else if(num >= 10){ result += "X"; num -= 10; }else if(num >= 9){ result += "IX"; num -= 9; } else if(num >= 5){ result += "V"; num -= 5; }else if(num >= 4){ result += "IV"; num -= 4; }else if(num >= 1){ result += "I"; num -= 1; } else{ break; } } return result; } 
 import java.util.Scanner; import java.io.*; public class LetteredNumerationSystem { public static void main(String args[]) { File file = new File("lettered.in"); try { Scanner input = new Scanner(file); int dataCollect = input.nextInt(); int sum = 0; String lineInput = ""; for (int i = 0; i <= dataCollect; i++) { while (input.hasNext()) { lineInput = input.next(); char lineArray[] = lineInput.toCharArray(); for (int j = 0; j < lineArray.length; j++) { if (lineArray[j] == 'A') { sum += 1; } else if (lineArray[j] == 'B') { sum += 10; } else if (lineArray[j] == 'C') { sum += 100; } else if (lineArray[j] == 'D') { sum += 1000; } else if (lineArray[j] == 'E') { sum += 10000; } else if (lineArray[j] == 'F') { sum += 100000; } else if (lineArray[j] == 'G') { sum += 1000000; } else if (lineArray[j] == 'X') { System.out.println(sum); sum = 0; } } } } } catch (FileNotFoundException e) { System.out.println("ERROR"); } } }