C#functon转换数字

时间:2017-05-22 11:21:26

标签: c# loops indexof

我正在尝试编写一个实用的函数来将带有罗马数字的输入转换为Decimal。我之前已经通过Javascript在2个方向上做过,但是在C#版本中,我在循环中遇到了迭代问题,而我还不知道如何使其工作。< / p>

class ToRoman
{
    public static int RomanToDecimal(string romanNums)
    {
        int result = 0; 

        int[] deci = new int[] {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        string[] roman = new string[] {"M", "CM", "D", "CD", "C", "XD", "L", "XL", "X", "IX", "V", "IV", "I"};

        for (int i = 0; i < deci.Length; i++)
        {
            while (romanNums.IndexOf(roman[i] == romanNums[i])
            {
                result += deci[i];
                romanNums = romanNums.Replace(roman[i]," ");
            }
        }
        return result;
    }

    static void Main()
    {
        Console.WriteLine(RomanToDecimal("V"));
        Console.WriteLine(RomanToDecimal("XIX"));
        Console.WriteLine(RomanToDecimal("MDXXVI"));
        Console.WriteLine(RomanToDecimal("MCCCXXXVII"));
    }
}

1 个答案:

答案 0 :(得分:1)

使用您的方法的第一个问题是您必须使用贪心算法:如果您有,请说CDL输入您应将其视为{ {1}},而不是CD + L == 440。另一个(可能是次要的)问题是您允许输入错误的输入,例如C + D + L == 640DDIIV等。

使用语法检查进行准确的实现,可以借助 FSA 有限状态自动机编写>)。例如。这些输入在语法上是不正确的:

XM

这样的事情:

   MIM, LL, XLX, CDC, XXXX, CCCXCX, CCCXL, VL, VX

一些测试:

private static Dictionary<char, int> s_Romans = new Dictionary<char, int>() {
  {'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50}, {'X', 10}, {'V', 5}, {'I', 1},
};

private static int RomanToArabic(string value) {
  if (null == value)
    throw new ArgumentNullException("value");
  else if (string.IsNullOrWhiteSpace(value))
    throw new ArgumentException("Empty or WS only value is not allowed.", "value");

  int v;

  int[] values = value
    .Select(c => s_Romans.TryGetValue(c, out v) ? v : -1)
    .ToArray();

  int result = 0;
  int current = 1000;
  int count = 0;

  for (int i = 0; i < values.Length; ++i) {
    v = values[i];

    if (v < 0)
      throw new FormatException($"Invalid symbol {value[i]} at {i + 1}");
    else if (v > current)
      throw new FormatException($"Invalid symbol {value[i]}");
    else if (current == v) {
      count += 1;

      if (count > 1 && (v == 5 || v == 50 || v == 500))
        throw new FormatException($"Invalid symbol {value[i]} at {i + 1}");
      else if (count > 3 && current != 1000)
        throw new FormatException($"Invalid symbol {value[i]} at {i + 1}");
    }
    else {
      count = 1;
      current = v;
    }

    if (i < value.Length - 1)
      if (v == 1 || v == 10 || v == 100)
        if (v * 5 == values[i + 1] || v * 10 == values[i + 1]) {
          v = values[i + 1] - v;
          count = 3;

          i += 1;
        }

    result += v;
  }

  return result;
}

更多测试:

Converting integers to roman numerals

// 4000
Console.Write(RomanToArabic("MMMM")); 
// 1444
Console.Write(RomanToArabic("MCDXLIV"));
// 1009
Console.Write(RomanToArabic("MIX"));
// 1
Console.Write(RomanToArabic("I"));