【问题标题】:Convert Int to Roman Numeral [closed]将 Int 转换为罗马数字 [关闭]
【发布时间】:2013-07-04 23:37:27
【问题描述】:

我的代码有问题。请帮忙。到目前为止,这是我的代码,我需要使用方法。它需要能够取整数 1-3999 并将其转换为罗马数字。有没有比我所做的更简单的方法来做到这一点?

    public static void main(String[] args) {
    Scanner in = new Scanner (System.in);
    System.out.print("Enter a number between 1 and 3999 (0 to quit): ");
    int input = in.nextInt();
    while (input !=0 )
    {
        if(input < 0 || input > 3999){
        System.out.println("ERROR! NUmber must be between 1 and 3999 (0 to quit): ");
        System.out.print("Enter a number between 1 and 3999 (0 to quit): ");
        input = in.nextInt();
        }
        else if(input > 0){
        String roman = convertNumberToNumeral(input);
        System.out.println("The number " + input + " is the Roman numberal " + roman);
        System.out.print("Enter a number between 1 and 3999 (0 to quit): ");
        input = in.nextInt();
        }
    }
    while (input == 0)
    {
        break;
    }
        System.out.println("Goodbye!");
}

// Given a Scanner as input, prompts the user to input a number between 1 and 3999.
// Checks to make sure the number is within range, and provides an error message until
// the user provides a value within range.  Returns the number input by the user to the
// calling program.
private static int promptUserForNumber(Scanner inScanner, int input) {
}

// Given a number as input, converts the number to a String in Roman numeral format, 
// following the rules in the writeup for Lab 09.  Returns the String to the calling
// program.  NOTE:  This method can possibly get long and complex.  Use the 
// convertDigitToNumeral method below to break this up and make it a bit simpler to code.
private static String convertNumberToNumeral(int input) {
    String romanOnes = ("");
    String romanTens = ("");
    String romanHundreds = ("");
    String romanThousands = ("");
    int ones = input % 10;
    int tens2 = input / 10;
    if (tens2 < 10)
    {
        tens2 = input / 10;
    }
    else {
        tens2 = tens2 % 100;
    }
    int tens = tens2;

    int hundreds2 = input / 100;
    if (hundreds2 < 10)
    {
        hundreds2 = input / 10;
    }
    else {
        hundreds2 = hundreds2 % 1000;
    }

    int hundreds = hundreds2;

    int thousands2 = input / 1000;
    if (thousands2 < 10)
    {
        thousands2 = input / 10;
    }
    else {
        thousands2 = thousands2 % 10000;
    }

    int thousands = input & 10000;
    {
        if (ones == 0)
        {
            romanOnes = ("");
        }
        else if (ones == 1)
        {
            romanOnes = ("I");
        }
        else if (ones == 2)
        {
            romanOnes = ("II");
        }
        else if(ones == 3)
        {
            romanOnes = ("III");
        }
        else if(ones == 4)
        {
            romanOnes = ("IV");
        }
        else if(ones == 5)
        {
            romanOnes = ("V");
        }
        else if(ones == 6)
        {
            romanOnes = ("VI");
        }
        else if(ones == 7)
        {
            romanOnes = ("VII");
        }
        else if(ones == 8)
        {
            romanOnes = ("VIII");
        }
        else if(ones == 9)
        {
            romanOnes = ("IX");
        }
    }
    {
        if (tens == 0)
        {
            romanTens = ("");
        }
        else if (tens == 1)
        {
            romanTens = ("X");
        }
        else if (tens == 2)
        {
            romanTens = ("XX");
        }
        else if(tens == 3)
        {
            romanTens = ("XXX");
        }
        else if(tens == 4)
        {
            romanTens = ("XL");
        }
        else if(tens == 5)
        {
            romanTens = ("L");
        }
        else if(tens == 6)
        {
            romanTens = ("LX");
        }
        else if(tens == 7)
        {
            romanTens = ("LXX");
        }
        else if(tens == 8)
        {
            romanTens = ("LXXX");
        }
        else if(tens == 9)
        {
            romanTens = ("XC");
        }
    }
    {
        if (hundreds == 0)
        {
            romanHundreds = ("");
        }
        else if (hundreds == 1)
        {
            romanHundreds = ("C");
        }
        else if (hundreds == 2)
        {
            romanHundreds = ("CC");
        }
        else if(hundreds == 3)
        {
            romanHundreds = ("CCC");
        }
        else if(hundreds == 4)
        {
            romanHundreds = ("CD");
        }
        else if(hundreds == 5)
        {
            romanHundreds = ("D");
        }
        else if(hundreds == 6)
        {
            romanHundreds = ("DC");
        }
        else if(hundreds == 7)
        {
            romanHundreds = ("DCC");
        }
        else if(hundreds == 8)
        {
            romanHundreds = ("DCCC");
        }
        else if(hundreds == 9)
        {
            romanHundreds = ("CM");
        }
    }
    {
        if (thousands == 0)
        {
            romanThousands = ("");
        }
        else if (thousands == 1)
        {
            romanThousands = ("M");
        }
        else if (thousands == 2)
        {
            romanThousands = ("MM");
        }
        else if(thousands == 3)
        {
            romanThousands = ("MMM");
        }
    }
    String roman = (romanThousands + romanHundreds + romanTens + romanOnes);
    return roman;

}

// Given a digit and the Roman numerals to use for the "one", "five" and "ten" positions,
// returns the appropriate Roman numeral for that digit.  For example, if the number to
// convert is 49 we would call convertDigitToNumeral twice.  The first call would be:
//     convertDigitToNumeral(9, 'I','V','X')
// and would return a value of "IX".  The second call would be:
//     convertDigitToNumeral(4, 'X','L','C')
// and would return a value of "XL".  Putting those togeter we would see that 49 would be the
// Roman numeral XLIX.
// Call this method from convertNumberToNumeral above to convert an entire number into a 
// Roman numeral.
private static String convertDigitToNumeral(int digit, char one, char five, char ten) {


}

【问题讨论】:

  • 当你得到很多 else if 时,考虑使用 switch 语句来代替(它提高了可读性,尤其是当多个案例给出相同的答案时)。
  • 仅供参考,在这个问题的答案中有几个很好的 Java 解决方案:Converting Integers to Roman Numerals - Java

标签: java


【解决方案1】:

哇!您似乎使这种方式太复杂了。 4clojure.com 上有一个非常相似的问题:Write Roman Numerals。您在这里有一些额外的错误检查逻辑,但即使如此,您也不应该需要这么多代码。我用 Clojure 中的 10 行函数解决了这个问题。但是,鉴于大多数人对 Lisps 不太满意,我将为您提供一个 Python 解决方案,它是我从 Clojure 解决方案中快速翻译过来的。

def to_roman(n):
  digits = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD' ),
            (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
            (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
  result = ""
  while len(digits) > 0:
    (val, romn) = digits[0] # Unpacks the first pair in the list
    if n < val:
      digits.pop(0) # Removes first element
    else:
      n -= val
      result += romn
  return result

Python 的语法很像伪代码,即使您实际上并不了解 Python,也可能理解它。我会留给你把它翻译成 Java。


回复您的评论:

我认为我的问题是使用方法,我如何使用我列出的方法?

您方法中的 cmets 非常清楚他们应该做什么。您需要使用Scanner 将所有代码从main 移动到promptUserForNumber。您将从main 调用promptUserForNumber 以获取有效的输入号码。

获得号码后,将其传递给convertNumberToNumeral 以处理转换。 convertNumberToNumeral 应该遍历数字的每个数字并调用 convertDigitToNumeral 将每个数字转换为相应的罗马数字字符串。在concatenating 之后所有的数字分量一起convertNumberToNumeral 可以返回完整的罗马数字表示字符串作为结果。

convertDigitToNumeral 的逻辑可以和我上面贴的to_roman 解决方案几乎相同,但你只需要处理一个数字。它看起来像这样:

def digit2roman(n, ten, five, one):
  digits = [(9, one+ten), (5, five), (4, one+five), (1, one)]
  result = ""
  while len(digits) > 0:
    val, romn = digits[0]
    if n < val:
      digits.pop(0)
    else:
      n -= val
      result += romn
  return result

digits 拆分为 2 个列表可能会更容易转换为 Java:

def digit2roman(n, ten, five, one):
  digitsV = [9, 5, 4, 1]
  digitsR = [one+ten, five, one+five, one]
  result = ""
  i = 0
  while i < len(digitsV):
    if n < digitsV[i]:
      i += 1
    else:
      n -= digitsV[i]
      result += digitsR[i]
  return result

在高级语言中,当您想同时迭代 2 个序列时,通常会将两个序列压缩成单个序列对,但在 Java 中,您通常只迭代索引。您应该可以轻松地使用 Java 数组翻译这段代码。

【讨论】:

  • 我认为我的问题是使用方法,我如何使用我列出的方法?
  • @user2509405 - 查看我的编辑。
【解决方案2】:
static HashMap<Character, Integer> numToInt;

public static void setup()
{
    numToInt = new HashMap<Character, Integer>();

// this is my trick to avoid listing the numbers
    String numerals = "MDCLXVI";
    int number = 1000;
    int factor = 2;
    for (char numeral : numerals.toCharArray()) {
        numToInt.put(numeral, number);
        number /= factor;
        factor = (factor == 2 ? 5 : 2);
    }
}

public static int romanNumeralsToInt(String numeralStr)
{
    int total = 0;
    int prevVal = 0;
    for (int i = 0; i < numeralStr.length(); i++) {
        int val = numToInt.get(numeralStr.charAt(i));
        total += val - (prevVal > val && prevVal != 0 ? 0 : 2 * prevVal);
        prevVal = val;
    }
    int len = numeralStr.length();
    return total;
}

【讨论】:

  • 单看这个,我觉得有些不对劲。您将I 设置为 1000,V 设置为 500,X 设置为 100,L 设置为 50(正确),C 设置为 10,D 设置为 5,M 设置为 1。
  • 我想你想从number = 1000, factor = 5开始,然后乘以因子而不是除。
  • 对不起,我把字母倒了。现在换了。谢谢@DaftPunk。
【解决方案3】:

@DaoWen 的回答非常好,但是由于convertDigitToNumeral 方法处理的情况很少,您可以硬编码所有这些情况。这是一个使用Java's format strings(使用位置参数)的简单解决方案:

private static final String[] digitFormats = new String[] {
  "", "%1$c", "%1$c%1$c", "%1$c%1$c%1$c", "%1$c%2$c",
  "%2$c", "%2$c%1$c", "%2$c%1$c%1$c", "%2$c%1$c%1$c%1$c", "%2$c%3$c"
};

private static String convertDigitToNumeral(int digit, char one, char five, char ten) {
  return String.format(digitFormats[digit], one, five, ten);
}

格式字符串"%2$c%1$c%1$c"five.toString() + one.toString() + one.toString()相同(假设格式参数按onefiveten的顺序传递)。

【讨论】:

    【解决方案4】:

    有没有更简单的方法?

    如前所述,您可以使用 HashTable 作为罗马代码的查找。您可以使用所有十个选项进行更大的查找,每个选项针对一个、十个和数百个。或者在答案中的python代码中使用一些算术来将其限制为所需的。

    如果你只是想让你的代码更具可读性:

    1. 浓缩您的计算。
    2. 将嵌套的 if 转换为 switch 语句。
    字符串结果 = ""; int 个 = 输入 % 10; 整数十=(输入/ 10)%10; int 数百 = (输入 / 100) % 10; 整数千 = 输入 / 1000; 开关(千) { 情况1: 结果=“M” 休息; 案例2: 结果=“MM” 休息; // ETC ... } 开关(十) { 情况1: 结果=结果+“C” 休息; // ETC .. } 开关(数百) { // ETC .. } 开关(一个) { // ETC .. } 返回结果;

    【讨论】:

    • 我不会切换(千)而是 new String(new char[thousands]).replace('\0','M');这首先创建一串空 (\0) 字符,然后将它们全部替换为 M。其他的也一样
    • @Xesau,有无数更好的方法来解决这个问题(一些已经建议)。正如我在回答中提到的,使用 switch 语句是在不改变逻辑的情况下“使 OP 的代码更具可读性”的建议。
    猜你喜欢
    • 1970-01-01
    • 2019-01-09
    • 2011-10-25
    • 1970-01-01
    • 2012-10-27
    • 2012-10-09
    • 1970-01-01
    相关资源
    最近更新 更多