2011-02-13 104 views

回答

31

最簡單的方法可能是設立三個陣列來複雜的情況下,用一個簡單的功能,如:

// 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'; 
} 

這將處理任何無符號整數,雖然大量將在一個可怕的很多M字符前端和調用者必須確保他們的緩衝區足夠大。

一旦數字減少到1000以下,這是一個簡單的3表查找,每個數字爲數百,數十和單位。例如,以val314的情況爲例。

val/100會在這種情況下3所以huns陣列查找會給CCC,然後val = val % 100給你14tens查找。

然後val/101在這種情況下,因此tens陣列查找會給X,然後val = val % 10給你4ones查找。

Then val4在那種情況下,所以ones陣列查找將給IV

這給了CCCXIV314


緩衝區溢出檢查版本是一個簡單的步驟,從那裏:

// 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; 
} 

雖然,在這一點上,你能想到重構的數百名,十位和個加工成的單獨的功能,因爲它們非常相似。我會把它作爲一個額外的練習。

0

我認爲ValueConverter是將整數轉換爲羅馬數字最優雅的方法之一。我希望但丁是不是太生氣,我在這裏發表他的代碼:

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; 
     } 
    } 
} 
-2
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; 
    } 
1

不使用娘娘腔預先計算的地圖的疑難雜症。

/* 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; 
} 

您實際上並不需要聲明S。應該很容易明白爲什麼。