Advertisement
Guest User

Untitled

a guest
Oct 18th, 2013
938
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.13 KB | None | 0 0
  1. /// Класс предназначен для преобразований арабских чисел в римские и обратно
  2. /// </summary>
  3. /// <remarks>
  4. /// <para>Класс изначально содержит алфавит римских чисел, способных определять арабские числа от 1 до 39999</para>
  5. /// <para>Если необходимо расширить диапазон, то можно определить дополнительные обозначения для римских чисел, используя
  6. /// поле <see cref="БазовыеРимскиеЧисла"/>БазовыеРимскиеЧисла</remarks>
  7. public static class РимскоеЧисло
  8. {
  9. /// <summary>
  10. /// Алфавит базовых римских чисел
  11. /// <para>Алфавит построен в виде словаря. Ключем словаря является арабское число (int), значением - соответствующее ему
  12. /// римское число (string)</para>
  13. /// </summary>
  14. /// <remarks>
  15. /// <para>Содержит римское обозначения арабских чисел 1*,4*,5*,9* - где "*"представляет собой 0...N нулей</para>
  16. /// <para>При создании содержит в себе обозначение чисел от 1 до 10000 (I...ↂ) Так как в римском числе один символ не может
  17. /// встречаться более трех раз, то изначально можно преобразовать в римский формат числа от 1 до 39999.</para>
  18. /// <para>Если Вы хотите иметь возможность работать с большим количеством римских чисел, то вы должны добавить в список
  19. /// дополнительные обозначения начиная с 40000 не пропуская элементы 1*,4*,5*,9*.</para>
  20. /// </remarks>
  21. public static SortedList<int, string> БазовыеРимскиеЧисла { get; set; }
  22.  
  23.  
  24.  
  25. static РимскоеЧисло()
  26. {
  27.         БазовыеРимскиеЧисла = new SortedList<int, string>(17);
  28.         БазовыеРимскиеЧисла.Add(1, "I");
  29.         БазовыеРимскиеЧисла.Add(4, "IV");
  30.         БазовыеРимскиеЧисла.Add(5, "V");
  31.         БазовыеРимскиеЧисла.Add(9, "IX");
  32.         БазовыеРимскиеЧисла.Add(10, "X");
  33.         БазовыеРимскиеЧисла.Add(40, "XL");
  34.         БазовыеРимскиеЧисла.Add(50, "L");
  35.         БазовыеРимскиеЧисла.Add(90, "XC");
  36.         БазовыеРимскиеЧисла.Add(100, "C");
  37.         БазовыеРимскиеЧисла.Add(400, "CD");
  38.         БазовыеРимскиеЧисла.Add(500, "D");
  39.         БазовыеРимскиеЧисла.Add(900, "CM");
  40.         БазовыеРимскиеЧисла.Add(1000, "M");
  41.         БазовыеРимскиеЧисла.Add(4000, "Mↁ");
  42.         БазовыеРимскиеЧисла.Add(5000, "ↁ");
  43.         БазовыеРимскиеЧисла.Add(9000, "Mↂ");
  44.         БазовыеРимскиеЧисла.Add(10000, "ↂ");
  45. }
  46.  
  47. /// <summary>
  48. /// Рассчитывает максимально возможное римское число для текущего алфавита римских чисел.
  49. /// </summary>
  50. /// <returns>Максимально возможное римское число</returns>
  51. public static uint МаксимальноеРимскоеЧисло()
  52. {
  53.         int последнееЧисло = БазовыеРимскиеЧисла.Keys.Last();
  54.         int числоБезНулей = int.Parse(последнееЧисло.ToString().Replace('0','\0'));
  55.         int предварительное=0;
  56.  
  57.         switch (числоБезНулей)
  58.         {
  59.                 case 1:
  60.                         предварительное = последнееЧисло * 4 - 1;
  61.                         break;
  62.                 case 4:
  63.                 case 9:
  64.                         предварительное = последнееЧисло;
  65.                         break;
  66.                 case 5:
  67.                         предварительное = последнееЧисло + последнееЧисло / 5 * 3;
  68.                         break;
  69.                 default:
  70.                         break;
  71.         }
  72.  
  73.         return uint.Parse(предварительное.ToString().Replace('0', '9'));;
  74. }
  75.  
  76. /// <summary>
  77. /// Конвентирует целое число в римское число
  78. /// </summary>
  79. /// <param name="числоАраб">Арабское число, которое необходимо преобразовать в римскую запись</param>
  80. /// <exception cref="ArgumentOutOfRangeException">Генерируется когда в качестве параметра передано число равное "0"
  81. /// или число большее чем максимальная римское число.</exception>
  82. /// <returns>Строку, представляющую собой римской число</returns>
  83. public static string АрабскоеВРимское(this int числоАраб)
  84. {
  85.         StringBuilder числоРимское = new StringBuilder();
  86.  
  87.         //Исключаем знак "-" из арабского числа и делаем его первым символом римского числа
  88.         if (числоАраб < 0)
  89.         {
  90.                 числоРимское.Append("-");
  91.                 числоАраб = -числоАраб;
  92.         }
  93.  
  94.         if (числоАраб == 0)
  95.                 throw new ArgumentOutOfRangeException("числоАраб", числоАраб,
  96.                         "Недопустимое значение аргумента: римские числа не могут быть равными\"0\"");
  97.         else if (числоАраб > МаксимальноеРимскоеЧисло())
  98.                 throw new ArgumentOutOfRangeException("числоАраб", числоАраб,
  99.                         string.Format("Недопустимое значение аргумента: невозможно задать римское число большее чем {0}",
  100.                                 МаксимальноеРимскоеЧисло()));
  101.  
  102.         //Раскладываем арабское число на составляющие его римские числа и объединяем их в одну строку
  103.         var необходимыеБазовыеРимскиеЧисла =
  104.                 from к in БазовыеРимскиеЧисла.Keys
  105.                 where к <= числоАраб
  106.                 orderby к descending
  107.                 select к;
  108.  
  109.         foreach (int тек in необходимыеБазовыеРимскиеЧисла)
  110.         {
  111.                 while ((числоАраб / тек) >= 1)
  112.                 {
  113.                         числоАраб -= тек;
  114.                         числоРимское.Append(БазовыеРимскиеЧисла[тек]);
  115.                 }
  116.         }
  117.  
  118.         return числоРимское.ToString();
  119. }
  120.  
  121.  
  122. /// <summary>
  123. /// Конвентирует римское число в арабское
  124. /// </summary>
  125. /// <param name="числоРимское">Римское число, которое необходимо преобразовать в тип int</param>
  126. /// <exception cref="FormatException">Генерируется когда в качестве параметра передано число не являющееся римским</exception>
  127. /// <returns>Целое число, представляющее собой арабскую запись римского числа</returns>
  128. public static int РимскоеВАрабское(this string числоРимское)
  129. {
  130.         int числоАраб = 0;
  131.         sbyte отрицательное = 1;
  132.         string рим = числоРимское.Trim();
  133.  
  134.         if (рим[0] == '-')
  135.         {
  136.                 отрицательное = -1;
  137.                 рим = рим.Substring(1);
  138.         }
  139.  
  140.         StringBuilder шаблонРимскогоНомера = new StringBuilder();
  141.  
  142.         foreach (int к in БазовыеРимскиеЧисла.Keys)
  143.         {
  144.                 int индекс = БазовыеРимскиеЧисла.Keys.IndexOf(к);
  145.                 string квантификатор="?";
  146.                 if (индекс == 0 || (индекс % 4) == 0)
  147.                         квантификатор="{0,3}";
  148.  
  149.                 шаблонРимскогоНомера.Insert(0, string.Format("(?<{0}>({1}){2})?", к.ToString(),
  150.                         БазовыеРимскиеЧисла[к], квантификатор));
  151.         }
  152.  
  153.         //Игнорировать регистр + соответствие должно начинаться с начала строки
  154.         шаблонРимскогоНомера.Insert(0, "(?i)^");
  155.         //Соответствие должно обнаруживаться в конце строки
  156.         шаблонРимскогоНомера.Append("$");
  157.  
  158.         //Упрощенная проверка. Не проверяет таких ошибок как IVII
  159.         if (!Regex.IsMatch(рим, шаблонРимскогоНомера.ToString()))
  160.                 throw new FormatException(string.Format("Текст \"{0}\" не является римским числом",числоРимское));
  161.  
  162.         Match число = Regex.Match(рим, шаблонРимскогоНомера.ToString());
  163.  
  164.  
  165.         foreach (int к in БазовыеРимскиеЧисла.Keys)
  166.         {
  167.                 числоАраб += число.Groups[к.ToString()].Length / БазовыеРимскиеЧисла[к].Length * к;
  168.         }
  169.  
  170.         return числоАраб * отрицательное;
  171. }
  172. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement