罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。
输入: num = 1994 输出: "MCMXCIV" 解释: M = 1000, CM = 900, XC = 90, IV = 4.
一、加减法
这里可以直接从最大的数值开始减,直到值比最大值小再进行下一个比较,直到值为零。
代码:
const vector<pair<int, string>> relMap = {
{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"},
};
string intToRoman(int num)
{
string str;
for (auto& p : relMap)
{
while (p.first <= num)
{
num -= p.first;
str += p.second;
}
if (num == 0)
{
break;
}
}
return str;
}
这里我一开始采取了非常笨拙的方法,就是先取出每一位的值然后根据位一一比较从而得到结果,这一编码过程较为繁琐,用以警告自己。
代码:
void valToChar(string& str, int val, char ch, char one, string four, string nine)
{
if (val == 0)
return;
if (val == 4)
{
str += four;
return;
}
if (val == 9)
{
str += nine;
return;
}
int k = val % 5;
for (int i = 0; i < k; i++)
{
str += one;
}
if (val >= 5)
{
str += ch;
}
return;
}
void intToRomanHandler(int count, int num, string& str)
{
switch (count)
{
case 1:
valToChar(str, num, 'V', 'I', "VI", "XI");
break;
case 2:
valToChar(str, num, 'L', 'X', "LX", "CX");
break;
case 3:
valToChar(str, num, 'D', 'C', "DC", "MC");
break;
case 4:
valToChar(str, num, ' ', 'M', "", "");
break;
default:
break;
}
}
string intToRoman(int num)
{
string str;
int tmp = num, count = 1;
while (tmp > 0)
{
int a = tmp % 10;
intToRomanHandler(count, a, str);
count++;
tmp /= 10;
}
std::reverse(str.begin(), str.end());
return str;
}