Преобразование числа в римские цифры на C#


Римские цифры - это древняя система счисления, но все еще встречающаяся в современном мире. Римские цифры используются для обозначения дат, украшают циферблаты часов и для индексации. В этой статье описывается алгоритм и код C# для преобразования числа в римские цифры.

Система римских цифр

Хотя система римских цифр очень стара, она все еще появляется в некоторых обстоятельствах. В кинематографе принято использовать римский эквивалент года производства для окончательного уведомления об авторских правах. В издательстве нумерация страниц и индексов содержания часто представлена таким образом.

В римской системе для обозначения чисел использовался ряд букв. Ключевые буквы были следующими:

римские цифры

Комбинирование цифр

Цифры могут быть объединены, чтобы создать все числа от одной до четырех тысяч, используя набор простых правил. Первое правило состоит в том, что буквы могут повторяться несколько раз, причем значения каждой из них являются аддитивными. Это означает, что I-Один, II-два, А III-три. Однако в современных представлениях IIII не верен для четырех, как мы увидим в третьем правиле.

Примечание: IIII иногда используется на циферблате часов. Для этого есть различные причины, в том числе эстетика цифр и придание некоторой симметрии часам.

Второе правило гласит, что большие цифры должны быть помещены слева от меньших цифр, чтобы продолжить аддитивную комбинацию. Таким образом, VI равно шести, а MDCLXI - 1661.

Третье правило позволяет расположить малозначное число слева от большего значения. Когда это происходит, например IX, меньшее число вычитается из большего. Это означает, что IX - девять, А IV-четыре. Однако это правило не может быть использовано повсеместно. Вычитаемая цифра должна составлять не менее одной десятой от значения большего числа. Соответственно, девяносто девять - это не IC, а скорее XCIX. часть XC представляет девяносто, а IX добавляет девять.

Для представления чисел от четырех тысяч и более к каждой букве добавляются строки. Например, строка над буквой умножает ее значение на тысячу. Для обозначения 15 015 римские цифры XVXV.

Наконец, существует очень мало информации, которая предполагает, что система изначально имела обозначение для нуля. Однако буква N использовалась для обозначения нуля в тексте примерно с 725 н.э.. Это будет использовано в алгоритме.

Цели алгоритма

Алгоритм преобразует целочисленное значение в римские цифры с помощью рекурсивного процесса. Результирующее значение возвращается в виде строки вызывающей функции. Чтобы устранить проблемы с отображением римских цифр четырех тысяч и более, вводится ограничение на значения от нуля до 3,999. Это должен быть достаточно большой диапазон для большинства применений.

Алгоритм и код

Подготовка

В зависимости от того, как вы хотите использовать этот алгоритм, вы можете создать его в новом классе, включить его в существующий класс или просто скрыть его за событием формы. Чтобы сохранить код простым и коротким, в этой статье предполагается, что у вас есть какой-то класс, подготовленный и добавляющий новый метод к этому классу. Код просто объявляет новый открытый метод, который принимает целое число, подлежащее преобразованию, в качестве своего единственного параметра.

Чтобы подготовить, создать или идентифицировать класс, в который будет добавлен метод, добавьте следующий код объявления:

public string NumberToRoman(int number)
{
}
Примечание: если вы создаете или добавляете в класс утилит, вы можете настроить объявление, чтобы сделать метод статическим. Если вы это сделаете, все другие объявления, описанные ниже, также должны быть помечены как статические.

Проверка целого числа

Преобразуемое число должно находиться в пределах ранее указанного диапазона. Если бы было предоставлено значение вне диапазона, результирующая строка была бы неправильной, поэтому включается правило проверки, которое создает исключение аргумента. Добавьте в этот метод следующий код проверки:

// валидация
if (number < 0 || number > 3999)
    throw new ArgumentException("Value must be in the range 0 - 3,999.");
Проверка на ноль

Если параметр, переданный методу, равен нулю, то результатом всегда будет 'N'. Это правило рассматривается отдельно от основного процесса преобразования для простоты. Следующий код, добавленный к методу, проверяет нулевое значение и, если оно найдено, немедленно возвращает результат:

if (number == 0) return "N";
Настройка ключевых значений

Алгоритм будет работать путем сравнения ряда значений с преобразуемым числом. Каждый элемент в серии представляет собой определенную букву римской цифры или пару букв, представляющих вычитание. Ключевыми цифрами будут M (1000), CM (900), D (500), CD (400), C (100), XC (90), L (50), XL (40), X (10), IX (9), V (5), IV (4) и I (1). Чтобы удержать эти значения и связать целое число с цифрой, мы создадим два массива. Это также может быть достигнуто с помощью коллекции, такой как SortedList.

int[] values = new int[] { 1000, 900, 500, 400, 100,90, 50, 40, 10, 9, 5, 4, 1 };
string[] numerals = new string[]
    { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
Инициализация результирующей строки

Результирующая строка будет строиться поэтапно с использованием объекта StringBuilder, так как это эффективно для рекурсивного добавления, которое будет происходить. Чтобы инициализировать StringBuilder, добавьте следующий код:

StringBuilder result = new StringBuilder();
Построение римских цифр

Теперь, когда все данные были инициализированы, необходимо разработать процесс добавления букв и пар в StringBuilder. Этот простой процесс проходит через все элементы в целочисленном массиве, начиная с самого большого значения. Если число, найденное в массиве, является таким же большим или больше, чем число, которое преобразуется, то соответствующая буква или пара или буквы из массива Numbers добавляются к StringBuilder.

Каждый раз, когда StringBuilder обновляется, преобразуемое число уменьшается на добавленную букву или значение пары. Это останавливает неправильное добавление цифр и гарантирует, что цикл не станет бесконечным. Итерационный процесс продолжается до тех пор, пока все значения в целочисленном массиве не будут обработаны и число, которое преобразуется, не будет сведено к нулю.

Код для цикла выглядит следующим образом:

for (int i = 0; i < 13; i++)
{
    while (number >= values[i])
    {
        number -= values[i];
        result.Append(numerals[i]);
    }
}
Завершение метода

Теперь остается только преобразовать значение StringBuilder в строку, чтобы оно могло быть возвращено вызывающей подпрограмме. Добавьте окончательный код, и вы будете готовы протестировать метод.

return result.ToString();
Итоговый код:

using System;
using System.Text;
					
public class Program
{
	
	public static string NumberToRoman(int number)
	{
		if (number < 0 || number > 3999)
    		throw new ArgumentException("Value must be in the range 0 - 3,999.");
		
		if (number == 0) return "N";
		
		int[] values = new int[] { 1000, 900, 500, 400, 100,90, 50, 40, 10, 9, 5, 4, 1 };
		string[] numerals = new string[]
    	{ "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
		
		
		StringBuilder result = new StringBuilder();
			
			
			for (int i = 0; i < 13; i++)
		{
    		while (number >= values[i]){
        		number -= values[i];
        		result.Append(numerals[i]);
    		}
		}
		
		return result.ToString();
	}
	
		
	public static void Main()
	{
		Console.WriteLine(NumberToRoman(19));
	}	
}
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, си шарп, алгоритмы, римские цифры




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Урок 8. Логические операторы C#
Реализация недвоичных деревьев
Шифрование строки с помощью C# и SHA-1