将整数转换为罗马数字

我正在尝试编写一个将数字转换为罗马数字的函数。 这是我的代码到目前为止; 但是,它只适用于小于400的数字。有没有一个简单快捷的方法来执行此转换,或扩展我现有的代码,以便处理所有情况? 在此先感谢您的帮助。

static string convertroman(int number) { int l = number / 10; StringBuilder sb = new StringBuilder(); for (int m = 0; m <= l; m++) { if (l == 0) { break; } if (l == 5) { sb = sb.Append(ro.L.ToString()); break; } if (l == 4) { sb = sb.Append(ro.X.ToString()).Append(ro.L.ToString()); break; } if (l == 9) { sb = sb.Append(ro.X.ToString()).Append(ro.C.ToString()); break; } if (l == 10) { sb = sb.Append(ro.C.ToString()); break; } if (l > 5 && l < 9) { sb = sb.Append(ro.L.ToString()); l = l - 5; m = 0; // break; continue; } if (l > 10) { sb = sb.Append(ro.C.ToString()); l = l - 10; m = 0; // continue; } else { sb = sb.Append(ro.X.ToString()); } } int z = number % 10; for (int x = 0; x <= z; x++) { if (z == 0) { break; } if (z == 5) { sb = sb.Append(ro.V.ToString()); break; } if (z == 4) { sb = sb.Append(ro.I.ToString()).Append(ro.V.ToString()); break; } if (z == 9) { sb = sb.Append(ro.I.ToString()).Append(ro.X.ToString()); break; } if (z == 10) { sb = sb.Append(ro.X.ToString()); break; } if (z > 5 && z < 9) { sb = sb.Append(ro.V.ToString()); z = z - 5; x = 0; } else { sb.Append(ro.I.ToString()); } } return sb.ToString(); } 

试试这个,简单而紧凑

 public static string ToRoman(int number) { if ((number < 0) || (number > 3999)) throw new ArgumentOutOfRangeException("insert value betwheen 1 and 3999"); if (number < 1) return string.Empty; if (number >= 1000) return "M" + ToRoman(number - 1000); if (number >= 900) return "CM" + ToRoman(number - 900); //EDIT: i've typed 400 instead 900 if (number >= 500) return "D" + ToRoman(number - 500); if (number >= 400) return "CD" + ToRoman(number - 400); if (number >= 100) return "C" + ToRoman(number - 100); if (number >= 90) return "XC" + ToRoman(number - 90); if (number >= 50) return "L" + ToRoman(number - 50); if (number >= 40) return "XL" + ToRoman(number - 40); if (number >= 10) return "X" + ToRoman(number - 10); if (number >= 9) return "IX" + ToRoman(number - 9); if (number >= 5) return "V" + ToRoman(number - 5); if (number >= 4) return "IV" + ToRoman(number - 4); if (number >= 1) return "I" + ToRoman(number - 1); throw new ArgumentOutOfRangeException("something bad happened"); } 

这里有一个更简单的algorithm – 原谅我,我不知道C#,所以我用JavaScript写这个,但同样的algorithm应该适用(我已经评论,所以你可以理解的algorithm):

 function intToRoman(int) { // create 2-dimensional array, each inner array containing // roman numeral representations of 1-9 in each respective // place (ones, tens, hundreds, etc...currently this handles // integers from 1-3999, but could be easily extended) var romanNumerals = [ ['', 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix'], // ones ['', 'x', 'xx', 'xxx', 'xl', 'l', 'lx', 'lxx', 'lxxx', 'xc'], // tens ['', 'c', 'cc', 'ccc', 'cd', 'd', 'dc', 'dcc', 'dccc', 'cm'], // hundreds ['', 'm', 'mm', 'mmm'] // thousands ]; // split integer string into array and reverse array var intArr = int.toString().split('').reverse(), len = intArr.length, romanNumeral = '', i = len; // starting with the highest place (for 3046, it would be the thousands // place, or 3), get the roman numeral representation for that place // and append it to the final roman numeral string while (i--) { romanNumeral += romanNumerals[ i ][ intArr[i] ]; } return romanNumeral; } console.log( intToRoman(3046) ); // outputs mmmxlvi 

我已经创build了这个类,它是decimal <=> roman

 public static class Roman { public static readonly Dictionary<char, int> RomanNumberDictionary; public static readonly Dictionary<int, string> NumberRomanDictionary; static Roman() { RomanNumberDictionary = new Dictionary<char, int> { { 'I', 1 }, { 'V', 5 }, { 'X', 10 }, { 'L', 50 }, { 'C', 100 }, { 'D', 500 }, { 'M', 1000 }, }; NumberRomanDictionary = new Dictionary<int, string> { { 1000, "M" }, { 900, "CM" }, { 500, "D" }, { 400, "CD" }, { 100, "C" }, { 50, "L" }, { 40, "XL" }, { 10, "X" }, { 9, "IX" }, { 5, "V" }, { 4, "IV" }, { 1, "I" }, }; } public static string To(int number) { var roman = new StringBuilder(); foreach (var item in NumberRomanDictionary) { while (number >= item.Key) { roman.Append(item.Value); number -= item.Key; } } return roman.ToString(); } public static int From(string roman) { int total = 0; int current, previous = 0; char currentRoman, previousRoman = '\0'; for (int i = 0; i < roman.Length; i++) { currentRoman = roman[i]; previous = previousRoman != '\0' ? RomanNumberDictionary[previousRoman] : '\0'; current = RomanNumberDictionary[currentRoman]; if (previous != 0 && current > previous) { total = total - (2 * previous) + current; } else { total += current; } previousRoman = currentRoman; } return total; } } 

部分unit testingTo方法:

 [TestClass] public class DecimalToRomanTest { [TestMethod] public void Roman_1_I() { Assert.AreEqual("I", Roman.To(1)); } [TestMethod] public void Roman_2_II() { Assert.AreEqual("II", Roman.To(2)); } [TestMethod] public void Roman_3_III() { Assert.AreEqual("III", Roman.To(3)); } [TestMethod] public void Roman_4_IV() { Assert.AreEqual("IV", Roman.To(4)); } [TestMethod] public void Roman_5_V() { Assert.AreEqual("V", Roman.To(5)); } [TestMethod] public void Roman_9_IX() { Assert.AreEqual("IX", Roman.To(9)); } [TestMethod] public void Roman_10_X() { Assert.AreEqual("X", Roman.To(10)); } [TestMethod] public void Roman_49_XLIX() { Assert.AreEqual("XLIX", Roman.To(49)); } [TestMethod] public void Roman_50_L() { Assert.AreEqual("L", Roman.To(50)); } [TestMethod] public void Roman_100_C() { Assert.AreEqual("C", Roman.To(100)); } [TestMethod] public void Roman_400_CD() { Assert.AreEqual("CD", Roman.To(400)); } [TestMethod] public void Roman_500_D() { Assert.AreEqual("D", Roman.To(500)); } [TestMethod] public void Roman_900_CM() { Assert.AreEqual("CM", Roman.To(900)); } [TestMethod] public void Roman_1000_M() { Assert.AreEqual("M", Roman.To(1000)); } [TestMethod] public void Roman_11984_MMMMMMMMMMMCMLXXXIV() { Assert.AreEqual("MMMMMMMMMMMCMLXXXIV", Roman.To(11984)); } } 

一些unit testing的From方法:

 [TestClass] public class RomanToDecimalTest { [TestMethod] public void Roman_I_1() { Assert.AreEqual(1, Roman.From("I")); } [TestMethod] public void Roman_II_2() { Assert.AreEqual(2, Roman.From("II")); } [TestMethod] public void Roman_III_3() { Assert.AreEqual(3, Roman.From("III")); } [TestMethod] public void Roman_IV_4() { Assert.AreEqual(4, Roman.From("IV")); } [TestMethod] public void Roman_V_5() { Assert.AreEqual(5, Roman.From("V")); } [TestMethod] public void Roman_IX_9() { Assert.AreEqual(9, Roman.From("IX")); } [TestMethod] public void Roman_X_10() { Assert.AreEqual(10, Roman.From("X")); } [TestMethod] public void Roman_XLIX_49() { Assert.AreEqual(49, Roman.From("XLIX")); } [TestMethod] public void Roman_L_50() { Assert.AreEqual(50, Roman.From("L")); } [TestMethod] public void Roman_C_100() { Assert.AreEqual(100, Roman.From("C")); } [TestMethod] public void Roman_CD_400() { Assert.AreEqual(400, Roman.From("CD")); } [TestMethod] public void Roman_D_500() { Assert.AreEqual(500, Roman.From("D")); } [TestMethod] public void Roman_CM_900() { Assert.AreEqual(900, Roman.From("CM")); } [TestMethod] public void Roman_M_1000() { Assert.AreEqual(1000, Roman.From("M")); } [TestMethod] public void Roman_MMMMMMMMMMMCMLXXXIV_11984() { Assert.AreEqual(11984, Roman.From("MMMMMMMMMMMCMLXXXIV")); } } 

这实际上是一个非常有趣的问题,基于dofactory.com上的反向示例(将罗马数字转换为小数)很容易扭转模式,也许稍微改进一下。 此代码将支持从1到3999999的数字。

从上下文类开始,这定义了parsing器的I / O

 public class Context { private int _input; private string _output; public Context(int input) { this._input = input; } public int Input { get { return _input; } set { _input = value; } } public string Output { get { return _output; } set { _output = value; } } } 

还有一个抽象expression式,它定义了parsing操作

 public abstract class Expression { public abstract void Interpret(Context value); } 

现在,您需要一个抽象terminalexpression式,它定义了将要执行的实际操作:

 public abstract class TerminalExpression : Expression { public override void Interpret(Context value) { while (value.Input - 9 * Multiplier() >= 0) { value.Output += Nine(); value.Input -= 9 * Multiplier(); } while (value.Input - 5 * Multiplier() >= 0) { value.Output += Five(); value.Input -= 5 * Multiplier(); } while (value.Input - 4 * Multiplier() >= 0) { value.Output += Four(); value.Input -= 4 * Multiplier(); } while (value.Input - Multiplier() >= 0) { value.Output += One(); value.Input -= Multiplier(); } } public abstract string One(); public abstract string Four(); public abstract string Five(); public abstract string Nine(); public abstract int Multiplier(); } 

然后,定义罗马数字行为的类(注意,我使用了小写的惯例,其中罗马数字用字母上的横条表示1000次)

 class MillionExpression : TerminalExpression { public override string One() { return "m"; } public override string Four() { return ""; } public override string Five() { return ""; } public override string Nine() { return ""; } public override int Multiplier() { return 1000000; } } class HundredThousandExpression : TerminalExpression { public override string One() { return "c"; } public override string Four() { return "cd"; } public override string Five() { return "d"; } public override string Nine() { return "cm"; } public override int Multiplier() { return 100000; } } class ThousandExpression : TerminalExpression { public override string One() { return "M"; } public override string Four() { return "Mv"; } public override string Five() { return "v"; } public override string Nine() { return "Mx"; } public override int Multiplier() { return 1000; } } class HundredExpression : TerminalExpression { public override string One() { return "C"; } public override string Four() { return "CD"; } public override string Five() { return "D"; } public override string Nine() { return "CM"; } public override int Multiplier() { return 100; } } class TenExpression : TerminalExpression { public override string One() { return "X"; } public override string Four() { return "XL"; } public override string Five() { return "L"; } public override string Nine() { return "XC"; } public override int Multiplier() { return 10; } } class OneExpression : TerminalExpression { public override string One() { return "I"; } public override string Four() { return "IV"; } public override string Five() { return "V"; } public override string Nine() { return "IX"; } public override int Multiplier() { return 1; } } 

几乎在那里,我们需要一个包含parsing树的非terminalexpression式:

 public class DecimalToRomaNumeralParser : Expression { private List<Expression> expressionTree = new List<Expression>() { new MillionExpression(), new HundredThousandExpression(), new TenThousandExpression(), new ThousandExpression(), new HundredExpression(), new TenExpression(), new OneExpression() }; public override void Interpret(Context value) { foreach (Expression exp in expressionTree) { exp.Interpret(value); } } } 

最后,客户端代码:

 Context ctx = new Context(123); var parser = new DecimalToRomaNumeralParser(); parser.Interpret(ctx); Console.WriteLine(ctx.Output); // Outputs CXXIII 

现场示例: http : //rextester.com/rundotnet?code=JJBYW89744

在1线,不是很有效,但工作:

 public string RomanNumeralFrom(int number) { return new string('I', number) .Replace(new string('I', 1000), "M") .Replace(new string('I', 900), "CM") .Replace(new string('I', 500), "D") .Replace(new string('I', 400), "CD") .Replace(new string('I', 100), "C") .Replace(new string('I', 90), "XC") .Replace(new string('I', 50), "L") .Replace(new string('I', 40), "XL") .Replace(new string('I', 10), "X") .Replace(new string('I', 9), "IX") .Replace(new string('I', 5), "V") .Replace(new string('I', 4), "IV"); } 

为时已晚,可能你已经解决了这个问题,但是这也是一个algorithm,可以帮你解决问题。

在开始之前,您可以简单地对罗马文字进行分析。 对于已知的ASCII集,只支持0到4000之间的值。 如果你想超越,那么你可以定义你自己的罗马字面。

在我们开始之前,我们知道在上面给定的范围内,我们可以从七个罗马文字(I,V,X,L,C,D和M)中形成一个罗马string。

因此,我们从一个简单的查找表开始,根据在另一个函数中计算的索引。 未知的索引作为空格字符返回。 正如我上面写的,在需要的时候可以添加额外的字符:

  /// <summary> /// Helper method that looks up a given index to it's roman value. /// </summary> /// <param name="decimalValue"></param> /// <returns>The roman literal corresponding to it's index</returns> private char DecimalToRoman(int index) { switch (index) { case 1: return 'I'; case 2: return 'V'; case 3: return 'X'; case 4: return 'L'; case 5: return 'C'; case 6: return 'D'; case 7: return 'M'; default: return ' '; } } 

真正的转换将在这里发生:

  private string ConvertToRoman(string input) { int index = 0; string output = ""; for (int i = 0; i < input.Length; i++) { //Some magic here, this formula will calculate the correct starting //index of the roman literal to find in the look-up table. //Since units, tens and hundreds (up to thousand) can be formed of //three roman literals, we need three indices for looking up the //correct roman literal. index = 2 * (input.Length - (i + 1)) + 1; char digit1 = DecimalToRoman(index); char digit2 = DecimalToRoman(index + 1); char digit3 = DecimalToRoman(index + 2); int originalValue = System.Convert.ToInt32(input[i] - '0'); switch (originalValue) { case 1: case 2: case 3: for (int j = 0; j < originalValue; j++) output += digit1.ToString(); break; case 4: output += digit1.ToString() + digit2.ToString(); break; case 5: output += digit2.ToString(); break; case 6: case 7: case 8: output += digit2.ToString(); for (int j = 0; j < originalValue - 5; j++) output += digit1.ToString(); break; case 9: output += digit1.ToString() + digit3.ToString(); break; } } return output; } 

这就对了。 如果您寻找更多OOdevise方法,请接受本post上方的答案。 有很多方法可以解决这个问题。

编辑:请注意,这种解决scheme不会作弊(只是查找所有的罗马文字的出现)以及:)

这是一个来自DotNetSnippets的超薄解决scheme

 private string ToRomanNumber(int number) { StringBuilder result = new StringBuilder(); int[] digitsValues = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; string[] romanDigits = { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M" }; while (number > 0) { for (int i = digitsValues.Count() - 1; i >= 0; i--) if (number / digitsValues[i] >= 1) { number -= digitsValues[i]; result.Append(romanDigits[i]); break; } } return result.ToString(); } 

这个版本不会像其他人那样“作弊”:它会在内部生成包含所有“基本”“可组合”数字的“基本”表。 对于懒惰我使用Tuple ,而不是创build专门的类。 如果你没有C#4.0,你可以用KeyValuePair<>replaceTuple<> KeyValuePair<>Item1KeyItem2Value

 static Tuple<IList<Tuple<string, int>>, int> GenerateBaseNumbers() { const string letters = "IVXLCDM"; var tuples = new List<Tuple<string, int>>(); Tuple<string, int> subtractor = null; int num = 1; int maxNumber = 0; for (int i = 0; i < letters.Length; i++) { string currentLetter = letters[i].ToString(); if (subtractor != null) { tuples.Add(Tuple.Create(subtractor.Item1 + currentLetter, num - subtractor.Item2)); } tuples.Add(Tuple.Create(currentLetter, num)); bool isEven = i % 2 == 0; if (isEven) { subtractor = tuples[tuples.Count - 1]; } maxNumber += isEven ? num * 3 : num; num *= isEven ? 5 : 2; } return Tuple.Create((IList<Tuple<string, int>>)new ReadOnlyCollection<Tuple<string, int>>(tuples), maxNumber); } static readonly Tuple<IList<Tuple<string, int>>, int> RomanBaseNumbers = GenerateBaseNumbers(); static string FromNumberToRoman(int num) { if (num <= 0 || num > RomanBaseNumbers.Item2) { throw new ArgumentOutOfRangeException(); } StringBuilder sb = new StringBuilder(); int i = RomanBaseNumbers.Item1.Count - 1; while (i >= 0) { var current = RomanBaseNumbers.Item1[i]; if (num >= current.Item2) { sb.Append(current.Item1); num -= current.Item2; } else { i--; } } return sb.ToString(); } static void Main(string[] args) { for (int i = 1; i <= RomanBaseNumbers.Item2; i++) { var calc = FromNumberToRoman(i); Console.WriteLine("{1}", i, calc); } } 

虽然我喜欢Mosta Bottacini的回答,但在这种情况下使用recursion有一些负面影响。 一个是可能的堆栈溢出,因此他限制了数字的上限。 然而,是的,我意识到罗马数字中巨大的数字是多么荒谬,但这仍然是一个不必要的结果。

另外,因为string是不可变的,由于大量使用string连接,他的版本将会非常低效。 下面是我的方法的修改版本,只使用一个while循环和一个StringBuilder。 我的版本实际上应该是更高性能的(尽pipe我们正在讨论亚毫秒范围内的差异),并且在系统内存上更容易一些。

 public static string ToRomanNumeral(this int value) { if (value < 0) throw new ArgumentOutOfRangeException("Please use a positive integer greater than zero."); StringBuilder sb = new StringBuilder(); int remain = value; while (remain > 0) { if (remain >= 1000) { sb.Append("M"); remain -= 1000; } else if (remain >= 900) { sb.Append("CM"); remain -= 900; } else if (remain >= 500) { sb.Append("D"); remain -= 500; } else if (remain >= 400) { sb.Append("CD"); remain -= 400; } else if (remain >= 100) { sb.Append("C"); remain -= 100; } else if (remain >= 90) { sb.Append("XC"); remain -= 90; } else if (remain >= 50) { sb.Append("L"); remain -= 50; } else if (remain >= 40) { sb.Append("XL"); remain -= 40; } else if (remain >= 10) { sb.Append("X"); remain -= 10; } else if (remain >= 9) { sb.Append("IX"); remain -= 9; } else if (remain >= 5) { sb.Append("V"); remain -= 5; } else if (remain >= 4) { sb.Append("IV"); remain -= 4; } else if (remain >= 1) { sb.Append("I"); remain -= 1; } else throw new Exception("Unexpected error."); // <<-- shouldn't be possble to get here, but it ensures that we will never have an infinite loop (in case the computer is on crack that day). } return sb.ToString(); } 

我可以提供一个比现有的方法更简单的方法

 using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; public class Form1 { int[] indx = { 1, 2, 3, 4, 5, 10, 50, 100, 500, 1000 // initialize array of integers }; string[] row = { "I", "II", "III", "IV", "V", "X", "L", "C", "D", "M" //Carasponding roman letters in for the numbers in the array }; // integer to indicate the position index for link two arrays int limit = 9; //string to store output string output = ""; private void Button1_Click(System.Object sender, System.EventArgs e) { int num = 0; // stores the input output = ""; // clear output before processing num = Convert.ToInt32(txt1.Text); // get integer value from the textbox //Loop until the value became 0 while (num > 0) { num = find(num); //call function for processing } txt2.Text = output; // display the output in text2 } public int find(int Num) { int i = 0; // loop variable initialized with 0 //Loop until the indx(i).value greater than or equal to num while (indx(i) <= Num) { i += 1; } // detemine the value of limit depends on the itetration if (i != 0) { limit = i - 1; } else { limit = 0; } output = output + row(limit); //row(limit) is appended with the output Num = Num - indx(limit); // calculate next num value return Num; //return num value for next itetration } } 

希望你曾经想过的最简单的解决scheme:)

 public string IntToRoman(int num) { string[] thou={"","M","MM","MMM"}; string[] hun={"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}; string[] ten={"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"}; string[] ones={"","I","II","III","IV","V","VI","VII","VIII","IX"}; string roman=""; roman += thou[(int)(num/1000)%10]; roman += hun[(int)(num/100)%10]; roman += ten[(int)(num/10)%10]; roman += ones[num%10]; return roman; } 

我试了一下,我的解决scheme如下所示:

 public class RomanNumeral { private readonly IDictionary<int, string> romanDictionary = new Dictionary<int, string> { {1, "I"}, {5, "V"}, {10, "X"}, {50, "L"}, {100, "C"}, {500, "D"}, {1000, "M"} }; private int factor = 1; public string Parse(int arabicNumber) { if (arabicNumber < 0) throw new ArgumentException(); var romanNumerals = new List<string>(); foreach (var number in arabicNumber.Split().Reverse()) { romanNumerals.Insert(0, ToRoman(number)); factor *= 10; } return romanNumerals.Concatenated(); } private string ToRoman(int number) { if (number.In(4, 9)) return ToRoman(1) + ToRoman(number + 1); if (number.In(6, 7, 8)) return ToRoman(number - 1) + ToRoman(1); if (number.In(2, 3)) return ToRoman(1) + ToRoman(number - 1); if (number == 0) return string.Empty; return romanDictionary[number * factor]; } } 
  public static int pairConversion(int dec, int lastNum, int lastDec) { if (lastNum > dec) return lastDec - dec; else return lastDec + dec; } public static int ConvertRomanNumtoInt(string strRomanValue) { var dec = 0; var lastNum = 0; foreach (var c in strRomanValue.Reverse()) { switch (c) { case 'I': dec = pairConversion(1, lastNum, dec); lastNum = 1; break; case 'V': dec=pairConversion(5,lastNum, dec); lastNum = 5; break; case 'X': dec = pairConversion(10, lastNum, dec); lastNum = 10; break; case 'L': dec = pairConversion(50, lastNum, dec); lastNum = 50; break; case 'C': dec = pairConversion(100, lastNum, dec); lastNum = 100; break; case 'D': dec = pairConversion(500, lastNum, dec); lastNum = 500; break; case 'M': dec = pairConversion(1000, lastNum, dec); lastNum = 1000; break; } } return dec; } 

如果将罗马数字倒过来处理像XIV这样的情况,会更容易。 代码是从这个博客引用。

 namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Enter the number\n"); int num = int.Parse(Console.ReadLine()); ToRomanNumber tr = new ToRomanNumber(); string opt=tr.ToRoman(num); Console.WriteLine(opt); } } class ToRomanNumber { string s = ""; public string ToRoman(int number) { if ((number < 0) || (number > 3999)) { s = s + "Invalid Input"; } if (number < 1) return s; if (number >= 1000) { s = s + "M"; ToRoman(number - 1000);} if (number >= 900){ s = s + "CM";ToRoman(number - 900);} if (number >= 500){ s = s + "D"; ToRoman(number - 500);} if (number >= 400){ s = s + "CD"; ToRoman(number - 400);} if (number >= 100){ s = s + "C"; ToRoman(number - 100);} if (number >= 90){ s = s + "XC"; ToRoman(number - 90);} if (number >= 50){ s = s + "L";ToRoman(number - 50);} if (number >= 40){ s = s + "XL";ToRoman(number - 40);} if (number >= 10){ s = s + "X"; ToRoman(number - 10); } if (number >= 9) { s = s + "IX"; ToRoman(number - 9); } if (number >= 5) { s = s + "V"; ToRoman(number - 5); } if (number >= 4) { s = s + "IV"; ToRoman(number - 4); } if (number >= 1) { s = s + "I"; ToRoman(number - 1);} return s; } } } 

我发现BrunoLM的代码非常简单和优雅,但From(…)函数确实需要检查源是否是有效的罗马数字。
像这样的东西

 public static bool IsValidRomanNumber(string source) { bool result = true; string[] invalidCouples = { "VV", "LL", "DD", "VX", "VC", "VM", "LC", "LM", "DM", "IC", "IM", "XM" }; foreach (string s in invalidCouples) { if (source.Contains(s)) { result = false; break; } } return result; } 
  Random r = new Random(); int[] arreglo = new int[100]; for (int i=0; i<arreglo.Length;i++) { arreglo[i] = r.Next(1,1001); } for (int t = 0;t < arreglo.Length; t++) { if (arreglo[t] >= 1000) { Console.Write("M"); arreglo[t] -= 1000; } if (arreglo[t] >=900) { Console.Write("MC"); arreglo[t] -= 900; } if (arreglo[t] >= 500) { Console.Write("D"); arreglo[t] -= 500; } if (arreglo[t] >= 400) { Console.Write("CD"); arreglo[t] -= 400; } if (arreglo[t] >= 100) { Console.Write("C"); arreglo[t] -= 100; } if (arreglo[t] >= 90) { Console.Write("XC"); arreglo[t] -= 90; } if (arreglo[t] >= 50) { Console.Write("L"); arreglo[t] -= 50; } if (arreglo[t] >= 40) { Console.Write("XL"); arreglo[t] -= 40; } if (arreglo[t] >= 10) { Console.Write("X"); arreglo[t] -= 10; } if (arreglo[t] >= 9) { Console.Write("IX"); arreglo[t] -= 9; } if (arreglo[t] >= 5) { Console.Write("V"); arreglo[t] -= 5; } if (arreglo[t] >= 4) { Console.Write("IV"); arreglo[t] -= 4; } if (arreglo[t] >= 1) { Console.Write("I"); arreglo[t] -= 1; } Console.WriteLine(); } Console.ReadKey(); 

解决scheme冗长,但初学者容易理解。 处理最多3000

 namespace RomansTranslator { using System; using System.Collections.Generic; /// <summary> /// Accepts a number (between 1 and 3000) and prints its Roman equivalent. /// </summary> class Program { static void Main(string[] args) { string number = string.Empty; Console.Write("Enter the Numeric number : "); number = Console.ReadLine(); if (IsValid(number)) // Validates the input { string roman = ConvertToRoman(number); Console.WriteLine("Roman Number is " + roman); } else { Console.WriteLine("Invalid Number"); } Console.ReadKey(); } private static string ConvertToRoman(string numberString) { string romanValue = string.Empty; int number = Convert.ToInt32(numberString); if (number >= 1) { // Loop through each roman character from highest foreach (int item in RomanDictionary().Keys) { while (number >= item) { romanValue = romanValue + RomanString(item); number -= item; } } } return romanValue; } /// <summary> /// Returns Roman Equvalent /// </summary> /// <param name="n"></param> /// <returns></returns> private static string RomanString(int n) { string romanString = string.Empty; romanString = RomanDictionary()[n].ToString(); return romanString; } /// <summary> /// List of Roman Characters /// </summary> /// <returns></returns> private static Dictionary<int, string> RomanDictionary() { Dictionary<int, string> romanDic = new Dictionary<int, string>(); romanDic.Add(1000, "M"); romanDic.Add(900, "CM"); romanDic.Add(500, "D"); romanDic.Add(400, "CD"); romanDic.Add(100, "C"); romanDic.Add(90, "XC"); romanDic.Add(50, "L"); romanDic.Add(40, "XL"); romanDic.Add(10, "X"); romanDic.Add(9, "IX"); romanDic.Add(5, "V"); romanDic.Add(4, "IV"); romanDic.Add(1, "I"); return romanDic; } /// <summary> /// Validates the Input /// </summary> /// <param name="input"></param> /// <returns></returns> private static bool IsValid(string input) { int value = 0; bool isValid = false; if (int.TryParse(input, out value)) { if (value <= 3000) { isValid = true; } } return isValid; } } } 

一个整洁,快速和直接的解决scheme

 function convertToRoman(num) { //Roman numerals to have <= 3 consecutive characters, the distances between deciaml values conform to this var decimalValue = [ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ]; var romanNumeral = [ 'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I' ]; var num_cp = num; // copy the function parameter into num_cp var result = ''; for (var i=0; i < decimalValue.length; i++){ //itarate through array of decimal values //iterate more to find values not explicitly provided in the decimalValue array while (decimalValue[i] <= num_cp){ result += romanNumeral[i]; num_cp -= decimalValue[i]; } } return result; } convertToRoman(477); 

这里是@Cammilius转换为C#的版本 – 在低数字上为我工作,这是我的用例所需要的。

 public String convertToRoman(int num) { //Roman numerals to have <= 3 consecutive characters, the distances between deciaml values conform to this int[] decimalValue = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; string[] romanNumeral = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; int num_cp = num; // copy the function parameter into num_cp String result = ""; for (var i = 0; i < decimalValue.Length; i = i + 1) { //itarate through array of decimal values //iterate more to find values not explicitly provided in the decimalValue array while (decimalValue[i] <= num_cp) { result = result + romanNumeral[i]; num_cp = num_cp - decimalValue[i]; } } return result; } 

一个更直接的解决scheme。 试图略微改善我使用StringBuilder的性能,通过更less的键迭代(当然LINQ的其中一个网站,可能会增加额外的延迟)

 public class ArabicToRomanConverter { private static readonly Dictionary<int, string> _romanDictionary = new Dictionary<int, string> { {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"} }; public ArabicToRomanConverter() { } public string Convert(int arabicNumber) { StringBuilder romanNumber = new StringBuilder(); var keys = _romanDictionary.Keys.Where(k => arabicNumber >= k).ToList(); for (int i = 0; i < keys.Count && arabicNumber > 0; i++) { int ckey = keys[i]; int division = arabicNumber / ckey; if (division != 0) { for (int j = 0; j < division; j++) { romanNumber.Append(_romanDictionary[ckey]); arabicNumber -= ckey; } } } return romanNumber.ToString(); } }