Conversion d’entiers en chiffres romains – Java

C’est un devoir avec lequel j’ai des problèmes.

Je dois faire un nombre entier au convertisseur de chiffres romains en utilisant une méthode. Plus tard, je dois ensuite utiliser le programme pour écrire 1 à 3999 en chiffres romains. Mon code ci-dessous est très nu; c’est une boucle d’E / S de base avec un moyen de sortir en utilisant un paquet pour getIntegerFromUser nous avons créé en classe.

Existe-t-il un moyen d’atsortingbuer des valeurs aux chaînes et de les append ensemble lorsque j’appelle la méthode?

Mise à jour: J’ai reçu un pseudo-code de mon professeur pour m’aider, et bien que je comprenne ce qu’il essaie de dire, j’ai des problèmes avec le if s. Aurai-je besoin de beaucoup d’énoncés pour que mon convertisseur gère correctement le formatage des chiffres romains ou existe-t-il une manière de le faire avec plus d’efficacité? J’ai mis à jour mon code pour refléter ma méthode des espaces réservés.

Mise à jour (28 octobre 2012): Je l’ai fait fonctionner. Voici ce que j’ai fini par utiliser:

 public static Ssortingng IntegerToRomanNumeral(int input) { if (input  3999) return "Invalid Roman Number Value"; Ssortingng 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; } 

Une implémentation compacte utilisant Java TreeMap et la récursivité:

 import java.util.TreeMap; public class RomanNumber { private final static TreeMap map = new TreeMap(); 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 Ssortingng toRoman(int number) { int l = map.floorKey(number); if ( number == l ) { return map.get(number); } return map.get(l) + toRoman(number-l); } } 

Essai:

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

Utilisez ces bibliothèques:

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

Le code:

  public static Ssortingng RomanNumerals(int Int) { LinkedHashMap roman_numerals = new LinkedHashMap(); 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); Ssortingng res = ""; for(Map.Entry entry : roman_numerals.entrySet()){ int matches = Int/entry.getValue(); res += repeat(entry.getKey(), matches); Int = Int % entry.getValue(); } return res; } public static Ssortingng repeat(Ssortingng s, int n) { if(s == null) { return null; } final SsortingngBuilder sb = new SsortingngBuilder(); for(int i = 0; i < n; i++) { sb.append(s); } return sb.toString(); } 

Tester le code:

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

Le résultat:

  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 

A partir du site Web 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 ssortingng that represents * a Roman numeral in this range. The function toSsortingng() 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 toSsortingng() function to construct the standard Roman numeral representation of the number. For each i, the number numbers[i] is represented by the corresponding ssortingng, letters[i]. */ private static int[] numbers = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; private static Ssortingng[] 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(Ssortingng roman) { if (roman.length() == 0) throw new NumberFormatException("An empty ssortingng does not define a Roman numeral."); roman = roman.toUpperCase(); // Convert to upper case letters. int i = 0; // A position in the ssortingng, roman; int arabic = 0; // Arabic numeral equivalent of the part of the ssortingng 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 ssortingng. 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 Ssortingng toSsortingng() { Ssortingng 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; } } 

Il y a en fait une autre façon de considérer ce problème, non pas comme un problème de nombre, mais comme un problème d’Unary, en commençant par le caractère de base des nombres romains, “I”. Donc, nous représentons le nombre avec juste moi, puis nous remplaçons les caractères en valeur croissante des caractères romains.

 public Ssortingng 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"); } 

J’aime particulièrement cette méthode de résolution de ce problème plutôt que d’utiliser beaucoup de boucles ifs et while ou de tables. Il s’agit en fait d’une solution intuitive lorsque vous considérez le problème comme un problème de nombre.

J’ai écrit une solution très simple. Tout ce que nous avons à faire est de diviser et de trouver combien de fois une lettre particulière (ou une combinaison de lettres se produit) et de l’append à l’object SsortingngBuilder sb . Nous devrions également garder une trace du nombre restant ( num ).

 public static Ssortingng intToRoman(int num) { SsortingngBuilder sb = new SsortingngBuilder(); int times = 0; Ssortingng[] romans = new Ssortingng[] { "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.toSsortingng(); } 

Je pense que ma solution est l’une des plus concises:

 private static Ssortingng convertToRoman(int mInt) { Ssortingng[] rnChars = { "M", "CM", "D", "C", "XC", "L", "X", "IX", "V", "I" }; int[] rnVals = { 1000, 900, 500, 100, 90, 50, 10, 9, 5, 1 }; Ssortingng 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 Ssortingng(new char[numberInPlace]).replace("\0",rnChars[i]); mInt = mInt % rnVals[i]; } return retVal; } 

J’aime la réponse d’André Kramer Orten, très élégante, j’aime particulièrement comment elle évite les boucles, j’ai pensé à une autre façon de la gérer en évitant les boucles.

Il utilise une division entière et un modulo sur l’entrée pour sélectionner l’index correct dans un ensemble de tableaux de chaînes codés en dur pour chaque type d’unité.

La bonne chose ici est que vous pouvez spécifier des conversions exactes en fonction de si vous voulez la forme numérique additive ou soustractive, c’est-à-dire IIII vs IV. Ici, j’utilise la “forme soustractive” pour tous les nombres sous la forme 5x-1 (4,9,14,19,40,90, etc.)

Il serait également sortingvial d’étendre cela pour permettre des nombres plus importants en étendant simplement le tableau des milliers avec d’autres formes additives ou soustractives, par exemple “IV”, “V” ou “MMMM”, “MMMMM”

Pour les points bonus, je m’assure que le paramètre number est compris dans la plage donnée pour le problème.

 public class RomanNumeralGenerator { static final int MIN_VALUE = 1; static final int MAX_VALUE = 3999; static final Ssortingng[] RN_M = {"", "M", "MM", "MMM"}; static final Ssortingng[] RN_C = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; static final Ssortingng[] RN_X = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; static final Ssortingng[] RN_I = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; public Ssortingng generate(int number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException( Ssortingng.format( "The number must be in the range [%d, %d]", MIN_VALUE, MAX_VALUE ) ); } return new SsortingngBuilder() .append(RN_M[number / 1000]) .append(RN_C[number % 1000 / 100]) .append(RN_X[number % 100 / 10]) .append(RN_I[number % 10]) .toSsortingng(); } } 
 Ssortingng convert(int i){ Ssortingng ones = ""; Ssortingng tens = ""; Ssortingng hundreds = ""; Ssortingng thousands = ""; Ssortingng 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; } 

Ma solution est en fonction getRoman:

 public Ssortingng getRoman(int number) { Ssortingng 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}; SsortingngBuilder result = new SsortingngBuilder(); 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.toSsortingng(); } 

Je suis curieux de savoir comment cela va finir. Je commencerais à examiner la cartographie 1,2,3,5,6,7,8,9,10 à I, II, III, IV, V, VI, VII, VII, IX, X … alors vous pourrait se pencher sur la règle pour les nombres romains: I, II, III sont créés par la concaténation V, X, L, C, D et M sont des symboles pour 5, 10, 50, 100, 500 et 1000 Les romains pensaient pouvoir économiser espace en écrivant des nombres au lieu d’écrire, par exemple IIII pour 4 utiliser IV (signifiant: 5 moins 1 …) Vous pourriez vouloir examiner ces règles, par exemple à http://en.wikipedia.org/wiki/Roman_numerals et les capturer dans le code par exemple dans une classe “RomanNumbers” Si vous souhaitez sortingcher, vous pouvez suivre le lien http://www.moxlotus.alternatifs.eu/programmation-converter.html

Je pense que si vous étudiez soigneusement la théorie des nombres romains, vous n’avez pas besoin de mappages pour les nombres 4,9,40, etc. car la théorie nous dit si le chiffre romain est IV = 5-1 = 4, donc plus petit que le préfixe. le numéro suivant dans ce cas vous devez soustraire l’ancien numéro du numéro suivant pour obtenir la valeur réelle et c’est ce que j’ai incorporé à mon code pour le problème, jetez un coup d’oeil et signalez les erreurs si nécessaire, j’ai suivi ceci table pour concevoir ma logique – 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 RomanSsortingngToIntegerConversion { public static void main(Ssortingng[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in))); Ssortingng[] romanSsortingng = br.readLine().split(""); HashMap romanToIntegerMap = new HashMap(); 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 = romanSsortingng.length; Set lessIndices = new HashSet(); 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); } } 

J’ai remarqué qu’il est assez facile de traduire un nombre entier par un chiffre romain, car il y a toujours une sorte de 1, 5 et 10 pour chaque chiffre ( I , V et X pour 1-10, X , L et C pour 10-100 etc. ) C’est pourquoi j’ai fait un tableau de chiffres romains pour obtenir la bonne lettre.

Dans mon exemple, je passe le chiffre entier un chiffre par heure, en utilisant l’opérateur modulo pour obtenir le dernier chiffre à chaque fois. Ensuite, je forme le chiffre romain du chiffre actuel dans une instruction switch, en l’ajoutant au début de la chaîne asRomanNumerals. Une fois le chiffre traduit, il est supprimé du numéro et l’index utilisé pour rechercher la lettre dans le tableau est augmenté de deux ( IVX -> XLC ).

 public static void main(Ssortingng[] 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 Ssortingng asRomanNumerals = ""; // Array including numerals in ascending order Ssortingng[] 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 Ssortingng 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.toSsortingng(); } public static void test(long n) { System.out.println(n + " = " + roman(n)); } public static void main(Ssortingng[] args) { test(1999); test(25); test(944); test(0); } 

Voici les résultats de mes devoirs. Il ne garantit pas que l’entrée est dans la bonne plage et je devrais probablement utiliser SsortingngBuilder (le temps que je l’ai cherché!) Et ne constitue pas une méthode unique. Mais si quelqu’un lisait aussi loin, j’apprécierais à la fois les retours positifs et négatifs!

 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(Ssortingng 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; } } 

Cela peut aider:

 using System; using System.Text; public class Test { public static ssortingng ToRoman(int number) { SsortingngBuilder br=new SsortingngBuilder(""); 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.ToSsortingng(); } public static void Main() { Console.WriteLine(ToRoman(int.Parse(Console.ReadLine()))); } } 

Après avoir vu certaines des réponses ici, j’ai dû poster ceci. Je pense que mon algorithme est le plus facile à comprendre et que la perte de performance n’est pas importante, même à une échelle relativement importante. J’obéis également aux conventions de codage standardisées, contrairement à certains utilisateurs ici.

Temps de conversion moyen: 0.05ms (basé sur la conversion de tous les nombres 1-3999 et la division par 3999)

 public static Ssortingng getRomanNumeral(int arabicNumber) { if (arabicNumber > 0 && arabicNumber < 4000) { final LinkedHashMap 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 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."); } } 

Tout d'abord, il faut tenir compte du fait que les chiffres romains se situent dans l'intervalle <1-4000), mais cela peut être résolu par une simple exception si et une seule fois. Vous pouvez ensuite essayer de trouver le plus grand nombre romain défini dans un entier donné et, si vous le trouvez, le soustraire du nombre original et l’ajouter au résultat. Répétez avec le nouveau numéro acquis jusqu'à ce que vous ayez atteint zéro.

Solution alternative basée sur la solution propre du PO en utilisant un enum . De plus, un parsingur et des tests aller-retour sont inclus.

 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 Ssortingng 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 Ssortingng 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.toSsortingng(); } public static int parse(Ssortingng roman) { if (roman.isEmpty()) { throw new NumberFormatException("The empty ssortingng 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; Ssortingng 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. } } } } 

After doing some research and analysing answers above, I ended up with this:

 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 Ssortingng[] letters = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"}; public static Ssortingng ssortingngToRoman(int num) { Ssortingng 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() { Ssortingng actual = RomanNumbers.ssortingngToRoman(1); Ssortingng expected = "I"; assertEquals(expected, actual); } @Test public void testReturn5() { Ssortingng actual = RomanNumbers.ssortingngToRoman(5); Ssortingng expected = "V"; assertEquals(expected, actual); } @Test public void testReturn2() { Ssortingng actual = RomanNumbers.ssortingngToRoman(2); Ssortingng expected = "II"; assertEquals(expected, actual); } @Test public void testReturn4() { Ssortingng actual = RomanNumbers.ssortingngToRoman(4); Ssortingng expected = "IV"; assertEquals(expected, actual); } @Test public void testReturn399() { Ssortingng actual = RomanNumbers.ssortingngToRoman(399); Ssortingng expected = "CCCXCIX"; assertEquals(expected, actual); } @Test public void testReturn3992() { Ssortingng actual = RomanNumbers.ssortingngToRoman(3992); Ssortingng expected = "MMMCMXCII"; assertEquals(expected, actual); } } 

Solution la plus simple:

 public class RomanNumerals { private static int [] arabic = {50, 40, 10, 9, 5, 4, 1}; private static Ssortingng [] roman = {"L", "XL", "X", "IX", "V", "IV", "I"}; public static Ssortingng convert(int arabicNumber) { SsortingngBuilder romanNumerals = new SsortingngBuilder(); int remainder = arabicNumber; for (int i=0;i= arabic[i]) { romanNumerals.append(roman[i]); remainder -= arabic[i]; } } return romanNumerals.toSsortingng(); } } 
 private Ssortingng convertToRoman(int num) { Ssortingng 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; } 

I did this before three years, may be it helps you:

 public class ToRoman { public static Ssortingng toRoman(int number) { SsortingngBuilder br = new SsortingngBuilder(""); while(number!=0) { while(number>=1000) { br.append("M"); number-=1000; } while(number>=900) { br.append("CM"); number-=900; } while(number>=500) { br.append("D"); number-=500; } while(number>=400) { br.append("CD"); number-=400; } while(number>=100) { br.append("C"); number-=100; } while(number>=90) { br.append("XC"); number-=90; } while(number>=50) { br.append("L"); number-=50; } while(number>=40) { br.append("XL"); number-=40; } while(number>=10) { br.append("X"); number-=10; } while(number>=9) { br.append("IX"); number-=9; } while(number>=5) { br.append("V"); number-=5; } while(number>=4) { br.append("IV"); number-=4; } while(number>=1) { br.append("I"); number-=1; } } return br.toSsortingng(); } public static void main(Ssortingng [] args) { System.out.println(toRoman(2000)); } } 
 private static Ssortingng toRoman(int n) { Ssortingng[] romanNumerals = { "M", "CM", "D", "CD", "C", "XC", "L", "X", "IX", "V", "I" }; int[] romanNumeralNums = { 1000, 900, 500, 400 , 100, 90, 50, 10, 9, 5, 1 }; Ssortingng finalRomanNum = ""; for (int i = 0; i < romanNumeralNums.length; i ++) { int currentNum = n /romanNumeralNums[i]; if (currentNum==0) { continue; } for (int j = 0; j < currentNum; j++) { finalRomanNum +=romanNumerals[i]; } n = n%romanNumeralNums[i]; } return finalRomanNum; } 
 import java.util.Scanner; import java.io.*; public class LetteredNumerationSystem { public static void main(Ssortingng args[]) { File file = new File("lettered.in"); try { Scanner input = new Scanner(file); int dataCollect = input.nextInt(); int sum = 0; Ssortingng 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"); } } }