J'essaie d'écrire une fonction qui convertit les nombres en chiffres romains. Ceci est mon code jusqu'à présent; toutefois, cela ne fonctionne qu'avec des nombres inférieurs à 400. Existe-t-il un moyen rapide et facile d'effectuer cette conversion ou d'étendre mon code existant de sorte qu'il gère tous les cas? Merci d'avance pour votre aide.
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();
}
Essayez ceci, simple et compact:
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);
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");
}
Voici un algorithme beaucoup plus simple - pardonnez-moi, je ne connais pas C #, donc j'écris ceci en JavaScript, mais le même algorithme devrait s'appliquer (et j'ai commenté pour que vous puissiez comprendre l'algorithme):
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
J'ai créé cette classe qui fait 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;
}
}
Quelques tests unitaires pour la méthode To
:
[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));
}
}
Quelques tests unitaires pour la méthode 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"));
}
}
C'est en fait un problème assez amusant, et basé sur l'exemple inverse de dofactory.com (convertissant les chiffres romains en décimales), il est assez facile d'inverser le motif, et peut-être de l'améliorer un peu. Ce code supportera les nombres de 1 à 3999999.
Commencer avec une classe de contexte, cela définit les E/S de l'analyseur
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; }
}
}
Et une expression abstraite, qui définit l'opération d'analyse
public abstract class Expression
{
public abstract void Interpret(Context value);
}
Maintenant, vous avez besoin d’une expression de terminal abstraite, qui définit l’opération réelle à exécuter:
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();
}
Ensuite, les classes qui définissent le comportement des chiffres romains (note, ive a utilisé la convention des minuscules où les chiffres romains utilisent une barre sur la lettre pour indiquer 1000 fois)
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; }
}
Presque là, nous avons besoin d’une expression non-terminale contenant l’arbre d’analyse:
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);
}
}
}
Enfin, le code client:
Context ctx = new Context(123);
var parser = new DecimalToRomaNumeralParser();
parser.Interpret(ctx);
Console.WriteLine(ctx.Output); // Outputs CXXIII
Exemple en direct: http://rextester.com/rundotnet?code=JJBYW89744
En 1 ligne, pas très efficace mais marche:
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");
}
Voici une solution mince de DotNetSnippets
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();
}
Espérons que la solution la plus simple que vous ayez jamais pensée :)
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;
}
Bien que j'aimais la réponse de Mosè Bottacini, l'utilisation de la récursion a quelques effets secondaires négatifs dans ce scénario. L'un étant le débordement possible de la pile, d'où sa limite supérieure du nombre. Bien que, oui, je réalise à quel point un grand nombre est ridicule en chiffres romains, il s'agit toujours d'une limitation qui n'est pas nécessaire pour obtenir le résultat.
De plus, comme les chaînes sont immuables, sa version va être très inefficace en mémoire, en raison de l'utilisation intensive de la concaténation de chaînes. Ci-dessous, ma version modifiée de sa méthode, utilisant juste une boucle while et un StringBuilder. Ma version devrait en réalité être plus performante (bien que nous parlions de différences dans la plage inférieure à une milliseconde) et beaucoup plus facile sur la mémoire système.
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();
}
Bien trop tard, vous avez probablement déjà résolu ce problème, mais c’est un algorithme qui peut également vous aider.
Avant de commencer, vous pouvez simplement faire l’analyse sur les littéraux romains. Pour l'ensemble ASCII connu, seules les valeurs comprises entre 0 et 4000 sont prises en charge. Si vous aimez aller au-delà, vous pouvez définir votre propre littéral romain alors.
Avant de commencer, nous savons qu'avec la plage donnée ci-dessus, nous pouvons former une chaîne romaine à partir de sept occurrences de littéraux romains (I, V, X, L, C, D et M).
Nous commençons donc par une simple table de correspondance, basée sur des indices calculés dans une autre fonction. Les index inconnus sont renvoyés sous forme de caractère d'espacement. Comme je l'ai écrit ci-dessus, on pourrait ajouter des caractères supplémentaires si nécessaire:
/// <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 ' ';
}
}
La vraie conversion aura lieu ici:
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;
}
C'est ça. Si vous recherchez plus de OO approches conçues, veuillez accepter les réponses ci-dessus. Il y a juste beaucoup de manières de résoudre cette approche.
EDIT: Notez que cette solution ne triche pas (il suffit de regarder toutes les occurrences de littéraux romains) :)
Cette version ne "triche" pas comme les autres: elle génère en interne la table "base" avec tous les nombres "base" "composables". Pour la paresse, j'utilise Tuple
s, au lieu de créer des classes spécialisées. Si vous ne possédez pas la version 4.0, vous pouvez remplacer Tuple<>
par KeyValuePair<>
, Item1
par Key
et Item2
par Value
.
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);
}
}
Je peux fournir une méthode qui est comparativement plus simple que l'existant
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
}
}
Une solution soignée, rapide et simple
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);
Une chaîne représentant le chiffre romain correspondant au numéro.
public static string ToRomanNumeral(this int number)
{
var retVal = new StringBuilder(5);
var valueMap = new SortedDictionary<int, string>
{
{ 1, "I" },
{ 4, "IV" },
{ 5, "V" },
{ 9, "IX" },
{ 10, "X" },
{ 40, "XL" },
{ 50, "L" },
{ 90, "XC" },
{ 100, "C" },
{ 400, "CD" },
{ 500, "D" },
{ 900, "CM" },
{ 1000, "M" },
};
foreach (var kvp in valueMap.Reverse())
{
while (number >= kvp.Key)
{
number -= kvp.Key;
retVal.Append(kvp.Value);
}
}
return retVal.ToString();
}
J'ai essayé et ma solution ressemble à ceci:
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];
}
}
Si ce problème était intéressant, c’est ce que j’ai pensé.
Il devrait (espérons-le) traite les nombres jusqu'à la limite supérieure des caractères surlignés. L'ajout de toute autre convention doit simplement consister à configurer de nouvelles bandes et à ajuster la chaîne ConfigureNext
.
NumeralGenerator.cs
public static class NumeralGenerator
{
private static readonly INumeralBand RootNumeralBand = ConfigureMapping();
private static INumeralBand ConfigureMapping()
{
var unitBand = new FinalBand(1, "I");
var fiveBand = new NumeralBand(5, "V", unitBand);
var tenBand = new NumeralBand(10, "X", unitBand);
var fiftyBand = new NumeralBand(50, "L", tenBand);
var hundredBand = new NumeralBand(100, "C", tenBand);
var fiveHundredBand = new NumeralBand(500, "D", hundredBand);
var thousandBand = new NumeralBand(1000, "M", hundredBand);
var thousandUnitBand = new NumeralBand(1000, "I\u0305", thousandBand);
var fiveThousandBand = new NumeralBand(5000, "V\u0305", thousandUnitBand);
var tenThousandBand = new NumeralBand(10000, "X\u0305", thousandUnitBand);
var fiftyThousandBand = new NumeralBand(50000, "L\u0305", tenThousandBand);
var hundredThousandBand = new NumeralBand(100000, "C\u0305", tenThousandBand);
var fiveHundredThousandBand = new NumeralBand(500000, "D\u0305", hundredThousandBand);
var millionBand = new NumeralBand(1000000, "M\u0305", hundredThousandBand);
millionBand
.ConfigureNext(fiveHundredThousandBand)
.ConfigureNext(hundredThousandBand)
.ConfigureNext(fiftyThousandBand)
.ConfigureNext(tenThousandBand)
.ConfigureNext(fiveThousandBand)
.ConfigureNext(thousandBand)
.ConfigureNext(fiveHundredBand)
.ConfigureNext(hundredBand)
.ConfigureNext(fiftyBand)
.ConfigureNext(tenBand)
.ConfigureNext(fiveBand)
.ConfigureNext(unitBand);
return millionBand;
}
public static string ToNumeral(int number)
{
var numerals = new StringBuilder();
RootNumeralBand.Process(number, numerals);
return numerals.ToString();
}
}
INumeralBand.cs
public interface INumeralBand
{
int Value { get; }
string Numeral { get; }
void Process(int number, StringBuilder numerals);
}
NumeralBand.cs
public class NumeralBand : INumeralBand
{
private readonly INumeralBand _negatedBy;
private INumeralBand _nextBand;
public NumeralBand(int value, string numeral, INumeralBand negatedBy)
{
_negatedBy = negatedBy;
Value = value;
Numeral = numeral;
}
public int Value { get; }
public string Numeral { get; }
public void Process(int number, StringBuilder numerals)
{
if (ShouldNegateAndStop(number))
{
numerals.Append(NegatedNumeral);
return;
}
var numeralCount = Math.Abs(number / Value);
var remainder = number % Value;
numerals.Append(string.Concat(Enumerable.Range(1, numeralCount).Select(x => Numeral)));
if (ShouldNegateAndContinue(remainder))
{
NegateAndContinue(numerals, remainder);
return;
}
if (remainder > 0)
_nextBand.Process(remainder, numerals);
}
private string NegatedNumeral => $"{_negatedBy.Numeral}{Numeral}";
private bool ShouldNegateAndStop(int number) => number == Value - _negatedBy.Value;
private bool ShouldNegateAndContinue(int number) => number >= Value - _negatedBy.Value;
private void NegateAndContinue(StringBuilder stringBuilder, int remainder)
{
stringBuilder.Append(NegatedNumeral);
remainder = remainder % (Value - _negatedBy.Value);
_nextBand.Process(remainder, stringBuilder);
}
public T ConfigureNext<T>(T nextBand) where T : INumeralBand
{
_nextBand = nextBand;
return nextBand;
}
}
FinalBand.cs
public class FinalBand : INumeralBand
{
public FinalBand(int value, string numeral)
{
Value = value;
Numeral = numeral;
}
public int Value { get; }
public string Numeral { get; }
public void Process(int number, StringBuilder numerals)
{
numerals.Append(new string(Numeral[0], number));
}
}
Les tests:
FinalBandTests.cs
public class FinalBandTests
{
[Theory]
[InlineData(1, "I")]
[InlineData(2, "II")]
[InlineData(3, "III")]
[InlineData(4, "IIII")]
public void Process(int number, string expected)
{
var stringBuilder = new StringBuilder();
var numeralBand = new FinalBand(1, "I");
numeralBand.Process(number, stringBuilder);
Assert.Equal(expected, stringBuilder.ToString());
}
}
NumeralBandTests.cs
public class NumeralBandTests
{
private Mock<INumeralBand> _nextBand;
private Mock<INumeralBand> _negatedBy;
private StringBuilder _stringBuilder;
public NumeralBandTests()
{
_stringBuilder = new StringBuilder();
_nextBand = new Mock<INumeralBand>();
_negatedBy = new Mock<INumeralBand>();
}
[Fact]
public void Process_NegateAndStop()
{
var numeral = new NumeralBand(10, "X", _negatedBy.Object);
_negatedBy.Setup(x => x.Value).Returns(1);
_negatedBy.Setup(x => x.Numeral).Returns("I");
numeral.Process(9, _stringBuilder);
Assert.Equal("IX", _stringBuilder.ToString());
_nextBand.Verify(x => x.Process(It.IsAny<int>(), It.IsAny<StringBuilder>()), Times.Never);
}
[Fact]
public void Process_Exact()
{
var numeral = new NumeralBand(10, "X", _negatedBy.Object);
_negatedBy.Setup(x => x.Value).Returns(1);
_negatedBy.Setup(x => x.Numeral).Returns("I");
numeral.Process(10, _stringBuilder);
Assert.Equal("X", _stringBuilder.ToString());
_nextBand.Verify(x => x.Process(It.IsAny<int>(), It.IsAny<StringBuilder>()), Times.Never);
}
[Fact]
public void Process_NegateAndContinue()
{
var numeral = new NumeralBand(50, "L", _negatedBy.Object);
numeral.ConfigureNext(_nextBand.Object);
_negatedBy.Setup(x => x.Value).Returns(10);
_negatedBy.Setup(x => x.Numeral).Returns("X");
numeral.Process(54, _stringBuilder);
Assert.Equal("L", _stringBuilder.ToString());
_nextBand.Verify(x => x.Process(4, _stringBuilder), Times.Once);
}
}
(NumeralGeneratorTests.cs} _
public class NumeralGeneratorTests
{
private readonly ITestOutputHelper _output;
public NumeralGeneratorTests(ITestOutputHelper output)
{
_output = output;
}
[Theory]
[InlineData(1, "I")]
[InlineData(2, "II")]
[InlineData(3, "III")]
[InlineData(4, "IV")]
[InlineData(5, "V")]
[InlineData(6, "VI")]
[InlineData(7, "VII")]
[InlineData(8, "VIII")]
[InlineData(9, "IX")]
[InlineData(10, "X")]
[InlineData(11, "XI")]
[InlineData(15, "XV")]
[InlineData(1490, "MCDXC")]
[InlineData(1480, "MCDLXXX")]
[InlineData(1580, "MDLXXX")]
[InlineData(1590, "MDXC")]
[InlineData(1594, "MDXCIV")]
[InlineData(1294, "MCCXCIV")]
[InlineData(3999, "MMMCMXCIX")]
[InlineData(4000, "I\u0305V\u0305")]
[InlineData(4001, "I\u0305V\u0305I")]
[InlineData(5002, "V\u0305II")]
[InlineData(10000, "X\u0305")]
[InlineData(15000, "X\u0305V\u0305")]
[InlineData(15494, "X\u0305V\u0305CDXCIV")]
[InlineData(2468523, "M\u0305M\u0305C\u0305D\u0305L\u0305X\u0305V\u0305MMMDXXIII")]
public void ToNumeral(int number, string expected)
{
var sw = Stopwatch.StartNew();
var actual = NumeralGenerator.ToNumeral(number);
sw.Stop();
_output.WriteLine(sw.ElapsedMilliseconds.ToString());
Assert.Equal(expected, actual);
}
}
Une autre solution simple. En essayant d’améliorer légèrement les performances, j’utilise StringBuilder, itère avec moins de clés (l’autre site, bien sûr, LINQ, où pourrait ajouter un délai supplémentaire)
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();
}
}
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;
}
Il serait plus facile si vous inversez les chiffres romains de traiter le cas comme XIV. Le code est référé de ce blog .
First create list of Tuples which contains numbers and corresponds.
Then a method/loops to iterate and return result.
IEnumerable<Tuple<int, string>> data = new List<Tuple<int, string>>()
{
new Tuple<int, string>( 1, "I"),
new Tuple<int, string>( 4, "IV" ),
new Tuple<int, string>( 5, "V" ),
new Tuple<int, string>( 9, "IX" ),
new Tuple<int, string>( 10, "X" ),
new Tuple<int, string>( 40, "XL" ),
new Tuple<int, string>( 50, "L" ),
new Tuple<int, string>( 90, "XC" ),
new Tuple<int, string>( 100, "C" ),
new Tuple<int, string>( 400, "CD" ),
new Tuple<int, string>( 500, "D" ),
new Tuple<int, string>( 900, "CM"),
new Tuple<int, string>( 1000, "M" )
};
public string ToConvert(decimal num)
{
data = data.OrderByDescending(o => o.Item1).ToList();
List<Tuple<int, string>> subData = data.Where(w => w.Item1 <= num).ToList();
StringBuilder sb = new StringBuilder();
foreach (var item in subData)
{
if (num >= item.Item1)
{
while (num >= item.Item1)
{
num -= item.Item1;
sb.Append(item.Item2.ToUpper());
}
}
}
return sb.ToString();
}
Solution remplissant les vérifications sémantiques de "notation soustractive"
Aucune des solutions actuelles ne remplit complètement l'ensemble des règles de la "notation soustractive". "IIII" -> n'est pas possible. 4. Chaque chaîne contient également les chaînes "CCCC", "VV", "IC" et "IM" non valides.
Un bon convertisseur en ligne pour vérifier la sémantique est https://www.romannumerals.org/converter Donc, si vous voulez vraiment faire un test de sémantique complet, c'est beaucoup plus complexe.
public class RomanNumerals
{
private List<Tuple<char, ushort, char?[]>> _validNumerals = new List<Tuple<char, ushort, char?[]>>()
{
new Tuple<char, ushort, char?[]>('I', 1, new char? [] {'V', 'X'}),
new Tuple<char, ushort, char?[]>('V', 5, null),
new Tuple<char, ushort, char?[]>('X', 10, new char?[] {'L', 'C'}),
new Tuple<char, ushort, char?[]>('L', 50, null),
new Tuple<char, ushort, char?[]>('C', 100, new char? [] {'D', 'M'}),
new Tuple<char, ushort, char?[]>('D', 500, null),
new Tuple<char, ushort, char?[]>('M', 1000, new char? [] {null, null})
};
public int TranslateRomanNumeral(string input)
{
var inputList = input?.ToUpper().ToList();
if (inputList == null || inputList.Any(x => _validNumerals.Select(t => t.Item1).Contains(x) == false))
{
throw new ArgumentException();
}
char? valForSubtraction = null;
int result = 0;
bool noAdding = false;
int equalSum = 0;
for (int i = 0; i < inputList.Count; i++)
{
var currentNumeral = _validNumerals.FirstOrDefault(s => s.Item1 == inputList[i]);
var nextNumeral = i < inputList.Count - 1 ? _validNumerals.FirstOrDefault(s => s.Item1 == inputList[i + 1]) : null;
bool currentIsDecimalPower = currentNumeral?.Item3?.Any() ?? false;
if (nextNumeral != null)
{
// Syntax and Semantics checks
if ((currentNumeral.Item2 < nextNumeral.Item2) && (currentIsDecimalPower == false || currentNumeral.Item3.Any(s => s == nextNumeral.Item1) == false) ||
(currentNumeral.Item2 == nextNumeral.Item2) && (currentIsDecimalPower == false || nextNumeral.Item1 == valForSubtraction) ||
(currentIsDecimalPower && result > 0 && ((nextNumeral.Item2 -currentNumeral.Item2) > result )) ||
(currentNumeral.Item2 > nextNumeral.Item2) && (nextNumeral.Item1 == valForSubtraction)
)
{
throw new ArgumentException();
}
if (currentNumeral.Item2 == nextNumeral.Item2)
{
equalSum += equalSum == 0 ? currentNumeral.Item2 + nextNumeral.Item2 : nextNumeral.Item2;
int? smallest = null;
var list = _validNumerals.Where(p => _validNumerals.FirstOrDefault(s => s.Item1 == currentNumeral.Item1).Item3.Any(s2 => s2 != null && s2 == p.Item1)).ToList();
if (list.Any())
{
smallest = list.Select(s3 => s3.Item2).ToList().Min();
}
// Another Semantics check
if (currentNumeral.Item3 != null && equalSum >= (smallest - currentNumeral.Item2))
{
throw new ArgumentException();
}
result += noAdding ? 0 : currentNumeral.Item2 + nextNumeral.Item2;
noAdding = !noAdding;
valForSubtraction = null;
}
else
if (currentNumeral.Item2 < nextNumeral.Item2)
{
equalSum = 0;
result += nextNumeral.Item2 - currentNumeral.Item2;
valForSubtraction = currentNumeral.Item1;
noAdding = true;
}
else
if (currentNumeral.Item2 > nextNumeral.Item2)
{
equalSum = 0;
result += noAdding ? 0 : currentNumeral.Item2;
noAdding = false;
valForSubtraction = null;
}
}
else
{
result += noAdding ? 0 : currentNumeral.Item2;
}
}
return result;
}
}
Voici la version de @Cammilius convertie en C # - fonctionne pour moi sur des nombres bas, ce qui est tout ce dont j'ai besoin pour mon cas d'utilisation.
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;
}
Voici mon effort, construit avec extension à l'esprit et, espérons-le, facile à comprendre, probablement pas la méthode la plus rapide cependant. Je voulais compléter ceci car obtenu dans le cadre du test d’entretien (qui était très démoralisant), il fallait d’abord comprendre le problème avant de pouvoir le résoudre.
Il devrait faire tous les chiffres, peut être vérifié ici https://www.calculateme.com/roman-numerals/from-roman
static void Main(string[] args)
{
CalculateRomanNumerals(1674);
}
private static void CalculateRomanNumerals(int integerInput)
{
foreach (var item in Enum.GetValues(typeof(RomanNumerals)).Cast<int>().Reverse())
{
integerInput = ProcessNumber(integerInput, item);
}
Console.ReadKey();
}
private static int ProcessNumber(int input, int number)
{
while (input >= number)
{
input -= number;
Console.Write((RomanNumerals)number);
}
return input;
}
enum RomanNumerals : int
{
I = 1,
IV = 4,
V = 5,
IX = 9,
X = 10,
L = 50,
XC = 90,
C = 100,
CD = 400,
D = 500,
CM = 900,
M = 1000
}
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;
}
}
}
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();
Je trouve le code de BrunoLM très simple et élégant, mais la fonction De (...) / Doit vraiment vérifier si la source est un chiffre romain valide.
Quelque chose comme ça
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;
}
public static String convert(int num)
{
String[] charsArray = {"I", "IV", "V", "IX", "X", "XL", "L", "XC","C","CD","D","CM","M" };
int[] charValuesArray = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
String resultString = "";
int temp = num;
int [] resultValues = new int[13];
// Generate an array which "char" occurances count
for(int i = 12 ; i >= 0 ; i--)
{
if((temp / charValuesArray[i]) > 0)
{
resultValues[i] = temp/charValuesArray[i];
temp = temp % charValuesArray[i];
}
}
// Print them if not occured do not print
for(int j = 12 ; j >= 0 ; j--)
{
for(int k = 0 ; k < resultValues[j]; k++)
{
resultString+= charsArray[j];
}
}
return resultString;
}
La solution est longue, mais facile à comprendre pour un débutant. Traiter jusqu'à 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;
}
}
}
@Backwards_Dave Vous vouliez une solution allant au nombre maximum, le voici:
public class ConvertDecimalNumberToRomanNumberType
{
public class RomanNumberType
{
public string RomanNumber;
public int RomanNumberValue;
}
public List<RomanNumberType> RomanNumbers;
public void Initialize()
{
RomanNumbers = new List<RomanNumberType>();
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "M", RomanNumberValue = 1000 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "CM", RomanNumberValue = 900 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "D", RomanNumberValue = 500 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "CD", RomanNumberValue = 400 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "C", RomanNumberValue = 100 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "XC", RomanNumberValue = 90 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "L", RomanNumberValue = 50 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "XL", RomanNumberValue = 40 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "X", RomanNumberValue = 10 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "IX", RomanNumberValue = 9 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "V", RomanNumberValue = 5 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "IV", RomanNumberValue = 4 });
RomanNumbers.Add(new RomanNumberType() { RomanNumber = "I", RomanNumberValue = 1 });
}
public string ConvertDecimalNumberToRomanNumber(int GetConvertDecimalNumberToRomanNumber)
{
string
FunctionResult
, CurrentRomanNumber = "";
int
FunctionGet = GetConvertDecimalNumberToRomanNumber
, DecimalNumberRemaining = FunctionGet;
foreach(RomanNumberType RomanNumber in RomanNumbers)
while(RomanNumber.RomanNumberValue <= DecimalNumberRemaining)
{
DecimalNumberRemaining -= RomanNumber.RomanNumberValue;
CurrentRomanNumber += RomanNumber.RomanNumber;
}
FunctionResult = CurrentRomanNumber;
return FunctionResult;
}
}
utilisation:
ConvertDecimalNumberToRomanNumberType ConvertDecimalNumberToRomanNumberObject = new ConvertDecimalNumberToRomanNumberType();
ConvertDecimalNumberToRomanNumberObject.Initialize();
var SomeVariable = ConvertDecimalNumberToRomanNumberObject.ConvertDecimalNumberToRomanNumber(1999);