我正在尝试编写一个实用的函数来将带有罗马数字的输入转换为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"));
}
}
答案 0 :(得分:1)
使用您的方法的第一个问题是您必须使用贪心算法:如果您有,请说CDL
输入您应将其视为{ {1}},而不是CD + L == 440
。另一个(可能是次要的)问题是您允许输入错误的输入,例如C + D + L == 640
或DD
,IIV
等。
使用语法检查进行准确的实现,可以借助 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"));