简体   繁体   中英

How do you find a roman numeral equivalent of an integer

How do you find a roman numeral equivalent of an integer. Is there a java library which provides this capability?

I did find a similar question , but I would prefer an out of the box API abstraction for this issue. Its just painful to handle all possible combinations in your code.

Here is a link for many languages including Java. Here's an extract of relevance:

public class RN {

    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);
    }

}

This is the code I am using, right next to the excel column name converter. Why isnt there an apache library for this stuff?

private static final char[] R = {'ↂ', 'ↁ', 'M', 'D', 'C', 'L', 'X', 'V', 'I'};
// or, as suggested by Andrei Fierbinteanu
// private static final String[] R = {"X\u0305", "V\u0305", "M", "D", "C", "L", "X", "V", "I"};
private static final int MAX = 10000; // value of R[0], must be a power of 10

private static final int[][] DIGITS = {
    {},{0},{0,0},{0,0,0},{0,1},{1},
    {1,0},{1,0,0},{1,0,0,0},{0,2}};

public static String int2roman(int number) {
    if (number < 0 || number >= MAX*4) throw new IllegalArgumentException(
            "int2roman: " + number + " is not between 0 and " + (MAX*4-1));
    if (number == 0) return "N";
    StringBuilder sb = new StringBuilder();
    int i = 0, m = MAX;
    while (number > 0) {
        int[] d = DIGITS[number / m];
        for (int n: d) sb.append(R[i-n]);
        number %= m;
        m /= 10;
        i += 2;
    }
    return sb.toString();
}

Edit:

Now that I look at it again, the loop can be condensed to

    for (int i = 0, m = MAX; m > 0; m /= 10, i += 2) {
        int[] d = DIGITS[(number/m)%10];
        for (int n: d) sb.append(R[i-n]);
    }

making the code even less readable ;-)

This my answer:

Use this libreries...

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

The code

  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 the code

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

The output:

  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

Best Regards

My version uses unmodified lookup and is more explicit.

 public String numToRoman(int num) {
    int numLength = (int) (Math.log10(num) + 1);
    int place_value = 10;
    final Map<Integer, char[]> romanModeLookup = new HashMap<>();
    romanModeLookup.putAll(Map.of(10, new char[]{'I', 'V', 'X'}, 100, new char[]{'X', 'L', 'C'},
            1000, new char[]{'C', 'D', 'M'}, 10000, new char[]{'M'}));


    final StringBuilder romanBuilder = new StringBuilder();
    while (numLength > 0) {
        numLength--;
        int current_num_at_place_val = (num % place_value) / (place_value / 10);
        System.out.println(current_num_at_place_val);

        if (place_value < 10000) {
            if (current_num_at_place_val == 9) {
                romanBuilder.append(romanModeLookup.get(place_value)[2]).append(romanModeLookup.get(place_value)[0]);
            } else if (current_num_at_place_val >= 5) {
                int remaining_sticks = current_num_at_place_val - 5;
                while (remaining_sticks > 0) {
                    romanBuilder.append(romanModeLookup.get(place_value)[0]);
                    remaining_sticks--;
                }
                romanBuilder.append(romanModeLookup.get(place_value)[1]);

            } else if (current_num_at_place_val == 4) {
                romanBuilder.append(romanModeLookup.get(place_value)[1]).append(romanModeLookup.get(place_value)[0]);
            } else {
                while (current_num_at_place_val > 0) {
                    romanBuilder.append(romanModeLookup.get(place_value)[0]);
                    current_num_at_place_val--;
                }
            }
        } else if (place_value == 10000) {
            while (current_num_at_place_val > 0) {
                romanBuilder.append(romanModeLookup.get(10000)[0]);
                current_num_at_place_val--;
            }
        } else {
            throw new IllegalArgumentException("Number too big for Romanization");
        }
        place_value *= 10;
    }

    return romanBuilder.reverse().toString();}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM