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

use*_*197 60 java methods roman-numerals

这是我遇到麻烦的家庭作业.

我需要使用方法为Roman Numeral转换器创建一个整数.之后,我必须使用该程序用罗马数字写出1到3999,所以硬编码就出来了.我的代码非常简单; 它是一个基本的I/O循环,在使用getIntegerFromUser我们在课堂上制作的包时可以退出.

有没有办法为字符串赋值,然后在调用方法时将它们一起添加?

更新:我从我的教授那里得到了一些伪代码来帮助我,虽然我明白他想说的是什么,但是我遇到了麻烦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;
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*ior 117

使用Java TreeMap和递归的紧凑实现:

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

}
Run Code Online (Sandbox Code Playgroud)

测试:

public void testRomanConversion() {

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

}
Run Code Online (Sandbox Code Playgroud)

  • @ElroyJetson TreeMap按自然顺序对键进行排序.方法TreeMap#floorKey在此解决方案中起着至关重要的作用,因为您可以方便地查找小于或等于给定键的最大键.如果存在完全匹配,则只返回相关的罗马符号,否则只需将小于给定数字的最大键关联的罗马符号连接到通过递归调用函数返回的罗马符号,使用当前数字减去先前找到的最大键. (6认同)
  • 我对这段代码的简洁和简洁感到敬畏.帽子. (4认同)
  • 您将如何创建使用此方法将罗马字符转回 Int 的方法? (2认同)

che*_*cho 28

使用这些库:

import java.util.LinkedHashMap;
import java.util.Map;
Run Code Online (Sandbox Code Playgroud)

代码:

  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();
  }
Run Code Online (Sandbox Code Playgroud)

测试代码:

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

输出:

  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
Run Code Online (Sandbox Code Playgroud)

  • 我不记得五年后。 (2认同)

Mor*_*hai 25

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


      }
Run Code Online (Sandbox Code Playgroud)

  • @ totymedli1这是一个教育网站.希望你能理解. (2认同)

小智 22

实际上有另一种看待这个问题的方法,不是一个数字问题,而是一个一元问题,从罗马数字的基本字符"I"开始.所以我们只用I表示数字,然后我们用罗马字符的升序值替换字符.

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");
}
Run Code Online (Sandbox Code Playgroud)

我特别喜欢这种解决这个问题的方法,而不是使用大量的ifs和while循环或表查找.当您认为问题不是一个数字问题时,它实际上也是一个退出直观的解决方案.

  • +1 - 避免循环很漂亮,我喜欢将其从数字问题转换为一元问题的想法。感觉受到启发,所以我也要把我的帽子扔进戒指里! (2认同)

Adi*_*dil 12

我写了一个非常简单的解决方案.我们所要做的就是划分并查找特定字母(或字母组合发生)的次数,并将其附加到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();
} 
Run Code Online (Sandbox Code Playgroud)


Fra*_*ser 9

我喜欢AndréKramerOrten的回答,非常优雅,我特别喜欢它如何避免循环,我想到了另一种方法来处理它也避免了循环.

它在输入上使用整数除法和模数,从每个单元类型的硬编码字符串数组中选择正确的索引.

这里的好处是你可以指定精确的转换,具体取决于你是否需要加法或减法数字形式,即IIII对IV.在这里,我使用5x-1(4,9,14,19,40,90等)形式的所有数字的"减法形式"

通过简单地使用其他加法或减法形式(即"IV","V"或"MMMM","MMMMM")扩展千位数组来扩展它以允许更大的数字也是微不足道的.

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不确定为什么这不是公认的答案.没有循环,没有生成一个庞大的字符串...我对[罗马数字从1到5000的列表]进行了测试(http://www.tuomas.salste.net/doc/roman/numeri-romani.html),这产生了正确的结果.我只需调整`RN_M`将"MMMM"添加到数组中. (2认同)

Dan*_*man 7

我认为我的解决方案之一是更简洁的解决方案之一:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 简明扼要,但仍然带有循环,而且远非可读。循环中的第 3 行很丑 - 三元运算符语法对它没有任何帮助!虽然很好 +1 (2认同)

Mar*_*k F 5

private static String toRoman(int n) {
    String[] 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 };
    String 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我们还需要为 4 和 40 添加数字,那么这将是一个完美的程序。 (3认同)

Wol*_*ahl 2

我很好奇这将如何结束。我开始研究映射 1,2,3,5,6,7,8,9,10 到 I,II,III,IV,V,VI,VII,VII,IX,X ...然后你可能会研究一下罗马数字的规则:I、II、III 是由连接创建的 V、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