Conversion d'entiers en chiffres romains en Java

Les chiffres romains utilisent sept symboles (I, V, X, L, C, D, M) combinés par addition et soustraction pour représenter les nombres de 1 à 3999. Un algorithme glouton en une dizaine de lignes Java suffit pour la conversion.

Le principe

On parcourt les valeurs romaines du plus grand au plus petit, en incluant les formes soustractives (IV = 4, IX = 9, XL = 40, etc.). À chaque étape, on ajoute le symbole autant de fois que la valeur entre dans le nombre restant.

Implémentation complète

public class ChiffresRomains {

    private static final int[]    VALEURS  = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    private static final String[] SYMBOLES = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

    public static String enRomain(int nombre) {
        if (nombre < 1 || nombre > 3999) {
            throw new IllegalArgumentException("Les chiffres romains classiques vont de 1 Ă  3999");
        }
        StringBuilder sortie = new StringBuilder();
        for (int i = 0; i < VALEURS.length; i++) {
            while (nombre >= VALEURS[i]) {
                sortie.append(SYMBOLES[i]);
                nombre -= VALEURS[i];
            }
        }
        return sortie.toString();
    }

    public static void main(String[] args) {
        for (int n : new int[]{1, 4, 9, 14, 49, 99, 500, 1999, 2026, 3999}) {
            System.out.printf("%4d = %s%n", n, enRomain(n));
        }
    }
}

Résultat :

   1 = I
   4 = IV
   9 = IX
  14 = XIV
  49 = XLIX
  99 = XCIX
 500 = D
1999 = MCMXCIX
2026 = MMXXVI
3999 = MMMCMXCIX

Conversion inverse — romain → entier

private static final Map<Character, Integer> TABLE = Map.of(
    'I', 1, 'V', 5, 'X', 10, 'L', 50, 'C', 100, 'D', 500, 'M', 1000
);

public static int enEntier(String romain) {
    int total = 0;
    for (int i = 0; i < romain.length(); i++) {
        int val = TABLE.get(romain.charAt(i));
        int suivant = (i + 1 < romain.length()) ? TABLE.get(romain.charAt(i + 1)) : 0;
        if (val < suivant) total -= val;
        else                total += val;
    }
    return total;
}

System.out.println(enEntier("MCMXCIX")); // 1999
System.out.println(enEntier("LVI"));     // 56

Règles à respecter

  • I, X, C, M peuvent se rĂ©pĂ©ter jusqu'Ă  3 fois (III, XXX).
  • V, L, D ne se rĂ©pètent jamais.
  • Formes soustractives autorisĂ©es : IV (4), IX (9), XL (40), XC (90), CD (400), CM (900).
  • Limite classique : 3999 (MMMCMXCIX).

Pour valider qu'une chaîne est un chiffre romain syntaxiquement correct, utilisez une expression régulière :

String regex = "^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$";
boolean valide = "MCMXCIX".matches(regex); // true

L'algorithme glouton fonctionne parce que les valeurs sont ordonnées : chaque choix localement optimal mène à la solution globale.