罗马数字以前只接触过I到VIII,第一次听说罗马数字也可以表示大于8的数字。阿拉伯数字和罗马数字之间的转换最重的是了解罗马数字的规则。Wiki了一把,又参考了其它的文档,总结如下:
罗马数字规则:
1, 罗马数字共有7个,即I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。
罗马数字中没有“0”。
2, 重复次数:一个罗马数字最多重复3次。
3, 右加左减:
在较大的罗马数字的右边记上较小的罗马数字,表示大数字加小数字。
在较大的罗马数字的左边记上较小的罗马数字,表示大数字减小数字。
4, 左减的数字有限制,仅限于I、X、C,且放在大数的左边只能用一个。
(*) V 和 X 左边的小数字只能用Ⅰ。
(*) L 和 C 左边的小数字只能用X。
(*) D 和 M 左 边的小数字只能用C。
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
int romanToInt(string s) {
map<char, int> dct;
dct['I'] = 1, dct['i'] = 1;
dct['V'] = 5, dct['v'] = 5;
dct['X'] = 10, dct['x'] = 10;
dct['L'] = 50, dct['l'] = 50;
dct['C'] = 100, dct['c'] = 100;
dct['D'] = 500, dct['d'] = 500;
dct['M'] = 1000, dct['m'] = 1000;
int sum = 0, j;
for(int i = 0; i < s.size(); ++i)
{
j = i+1;
if(j < s.size() && dct[s[j]] > dct[s[i]])
{
sum += dct[s[j]] - dct[s[i]];
i = j;
}
else
sum += dct[s[i]];
}
return sum;
}
代码实际上很简单,向前看一位。比较当前位及下一位的值,再确定是加还是减。Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
struct node{
int key;
string szRoman;
node(int k, string s):key(k), szRoman(s){}
};
string intToRoman(int num){
vector<node> dct;
dct.push_back(node(1000, "M"));
dct.push_back(node(900, "CM"));
dct.push_back(node(500, "D"));
dct.push_back(node(400, "CD"));
dct.push_back(node(100, "C"));
dct.push_back(node(90, "XC"));
dct.push_back(node(50, "L"));
dct.push_back(node(40, "XL"));
dct.push_back(node(10, "X"));
dct.push_back(node(9, "IX"));
dct.push_back(node(5, "V"));
dct.push_back(node(4, "IV"));
dct.push_back(node(1, "I"));
string res;
int i = 0;
while(num > 0)
{
if(num/dct[i].key == 0)
{
i += 1;
continue;
}
for(int j = 0; j < num/dct[i].key; ++j)
res.append(dct[i].szRoman);
num%=dct[i].key;
}
return res;
}
本人偷懒了,先搞了一张表,然后遍历表。表中比较特殊的值有900, 400, 90, 40, 9, 4,这些都是根据规则4得来的。
参考文献:
http://www.onlineconversion.com/roman_numerals_advanced.htm