visual valor romanos pseint programa pero para numeros numero naturales mismo entero convertir conversor con cambiar arabigos arabes algoritmo c roman-numerals

pseint - ¿Cómo convertir un valor entero en una cadena de números romanos?



numeros arabes conversor (4)

¿Cómo puedo convertir un número entero a su representación de cadena en números romanos en C?


Creo que ValueConverter es uno de los métodos más elegantes para convertir un número entero en un número romano. Espero que Dante no esté demasiado enojado por haber publicado su código aquí:

public class RomanNumeralizer : IValueConverter { private static IList<RomanNumeralPair> _Pairs; static RomanNumeralizer() { var list = new List<RomanNumeralPair>(); list.Add(new RomanNumeralPair(1000, "M")); list.Add(new RomanNumeralPair(900, "CM")); list.Add(new RomanNumeralPair(500, "D")); list.Add(new RomanNumeralPair(400, "CD")); list.Add(new RomanNumeralPair(100, "C")); list.Add(new RomanNumeralPair(90, "XC")); list.Add(new RomanNumeralPair(50, "L")); list.Add(new RomanNumeralPair(40, "XL")); list.Add(new RomanNumeralPair(10, "X")); list.Add(new RomanNumeralPair(9, "IX")); list.Add(new RomanNumeralPair(5, "V")); list.Add(new RomanNumeralPair(4, "IV")); list.Add(new RomanNumeralPair(1, "I")); _Pairs = list.AsReadOnly(); } private IList<RomanNumeralPair> PairSet { get { return _Pairs; } } public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ConvertToRomanNumeral(System.Convert.ToInt32(value)); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return null; } private string ConvertToRomanNumeral(int input) { StringBuilder myBuilder = new StringBuilder(); foreach (RomanNumeralPair thisPair in _Pairs) { while (input >= thisPair.Value) { myBuilder.Append(thisPair.RomanValue); input -= thisPair.Value; } } return myBuilder.ToString(); } } public class RomanNumeralPair { private string _RomanValue; private int _Value; public RomanNumeralPair(int value, string stringValue) { this._Value = value; this._RomanValue = stringValue; } public string RomanValue { get { return this._RomanValue; } } public int Value { get { return this._Value; } } }


La forma más fácil es probablemente configurar tres matrices para los casos complejos y usar una función simple como:

// convertToRoman: // In: val: value to convert. // res: buffer to hold result. // Out: n/a // Cav: caller responsible for buffer size. void convertToRoman (unsigned int val, char *res) { char *huns[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; char *tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; char *ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; int size[] = { 0, 1, 2, 3, 2, 1, 2, 3, 4, 2}; // Add ''M'' until we drop below 1000. while (val >= 1000) { *res++ = ''M''; val -= 1000; } // Add each of the correct elements, adjusting as we go. strcpy (res, huns[val/100]); res += size[val/100]; val = val % 100; strcpy (res, tens[val/10]); res += size[val/10]; val = val % 10; strcpy (res, ones[val]); res += size[val]; // Finish string off. *res = ''/0''; }

Esto manejará cualquier entero sin signo, aunque los números grandes tendrán una gran cantidad de M caracteres en el frente y la persona que llama tiene que asegurarse de que su búfer sea lo suficientemente grande.

Una vez que el número se ha reducido por debajo de 1000, se trata de una búsqueda simple de 3 mesas, una por cada cientos, decenas y unidades. Por ejemplo, tomemos el caso donde val es 314 .

val/100 será 3 en ese caso, por lo que la búsqueda de la matriz Huns dará CCC , luego val = val % 100 le da 14 para la búsqueda de tens .

Entonces, val/10 será 1 en ese caso, por lo que la búsqueda en la matriz de tens dará X , luego val = val % 10 le da 4 para ones búsquedas.

Entonces, val será 4 en ese caso, por lo ones búsqueda en la matriz dará IV .

Eso te da CCCXIV para 314 .

Una versión de comprobación de desbordamiento de búfer es un paso simple desde allí:

// convertToRoman: // In: val: value to convert. // res: buffer to hold result. // Out: returns 0 if not enough space, else 1. // Cav: n/a int convertToRoman (unsigned int val, char *res, size_t sz) { char *huns[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; char *tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; char *ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; int size[] = { 0, 1, 2, 3, 2, 1, 2, 3, 4, 2}; // Add ''M'' until we drop below 1000. while (val >= 1000) { if (sz-- < 1) return 0; *res++ = ''M''; val -= 1000; } // Add each of the correct elements, adjusting as we go. if (sz < size[val/100]) return 0; sz -= size[val/100]; strcpy (res, huns[val/100]); res += size[val/100]; val = val % 100; if (sz < size[val/10]) return 0; sz -= size[val/10]; strcpy (res, tens[val/10]); res += size[val/10]; val = val % 10; if (sz < size[val) return 0; sz -= size[val]; strcpy (res, ones[val]); res += size[val]; // Finish string off. if (sz < 1) return 0; *res = ''/0''; return 1; }

aunque, en ese momento, podría pensar en refactorizar el procesamiento de cientos, decenas y unidades en una función separada, ya que son muy similares. Dejaré eso como un ejercicio extra.


No utilice un mapa precargado de mariquita para los casos difíciles.

/* roman.c */ #include <stdio.h> /* LH(1) roman numeral conversion */ int RN_LH1 (char *buf, const size_t maxlen, int n) { int S[] = { 0, 2, 4, 2, 4, 2, 4 }; int D[] = { 1000, 500, 100, 50, 10, 5, 1 }; char C[] = { ''M'', ''D'', ''C'', ''L'', ''X'', ''V'', ''I'' }; const size_t L = sizeof(D) / sizeof(int) - 1; size_t k = 0; /* index into output buffer */ int i = 0; /* index into maps */ int r, r2; while (n > 0) { if (D[i] <= n) { r = n / D[i]; n = n - (r * D[i]); /* lookahead */ r2 = n / D[i+1]; if (i < L && r2 >= S[i+1]) { /* will violate repeat boundary on next pass */ n = n - (r2 * D[i+1]); if (k < maxlen) buf[k++] = C[i+1]; if (k < maxlen) buf[k++] = C[i-1]; } else if (S[i] && r >= S[i]) { /* violated repeat boundary on this pass */ if (k < maxlen) buf[k++] = C[i]; if (k < maxlen) buf[k++] = C[i-1]; } else while (r-- > 0 && k < maxlen) buf[k++] = C[i]; } i++; } if (k < maxlen) buf[k] = ''/0''; return k; } /* gcc -Wall -ansi roman.c */ int main (int argc, char **argv) { char buf[1024] = {''/0''}; size_t len; int k; for (k = 1991; k < 2047; k++) { len = RN_LH1(buf, 1023, k); printf("%3lu % 4d %s/n", len, k, buf); } return 0; }

en realidad no es necesario declarar S tampoco. Debería ser fácil ver por qué.


static string ConvertToRoman(int num) { int d = 0; string result = ""; while (num > 0) { int n = num % 10; result = DigitToRoman(n, d) + result; d++; num = num / 10; } return result; } static string DigitToRoman(int n, int d) { string[,] map = new string[3, 3] { { "I", "V", "X" }, { "X", "L", "C" }, { "C", "D", "M" } }; string result=""; if (d <= 2) { switch (n) { case 0: result = ""; break; case 1: result = map[d, 0]; break; case 2: result = map[d, 0] + map[d, 0]; break; case 3: result = map[d, 0] + map[d, 0] + map[d, 0]; break; case 4: result = map[d, 0] + map[d, 1]; break; case 5: result = map[d, 1]; break; case 6: result = map[d, 1] + map[d, 0]; break; case 7: result = map[d, 1] + map[d, 0] + map[d, 0]; break; case 8: result = map[d, 1] + map[d, 0] + map[d, 0] + map[d, 0]; break; case 9: result = map[d, 0] + map[d, 2]; break; } } else if (d == 3 && n < 5) { while (--n >= 0) { result += "M"; } } else { return "Error! Can''t convert numbers larger than 4999."; } return result; }