大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C++技巧 > 罗马数字和阿拉伯数字的转换

罗马数字和阿拉伯数字的转换

关键词:罗马数字阿拉伯数字转换  阅读(4798) 赞(15)

[摘要]本文是对罗马数字和阿拉伯数字的转换的讲解,对学习C++编程技术有所帮助,与大家分享。

【题目】

给出一个罗马数字,转换为阿拉伯数字。本题只考虑3999以内的数。

罗马数字有如下符号:

Ⅰ(1)Ⅴ(5)Ⅹ(10)L(50)C(100)D(500)M(1000)

计数规则:

(1).若干相同数字连写表示的数是这些罗马数字的和,如III=3;

(2).小数字在大数字前面表示的数是用大数字减去小数字,如IV=4;

(3).小数字在大数字后面表示的数是用大数字加上小数字,如VI=6;

组合规则:

(1)基本数字Ⅰ、X 、C 中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个;放在大数的左边只能用一个。

(2)不能把基本数字 V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目,只能使用一个。

(3)V 和 X 左边的小数字只能用Ⅰ。

(4)L 和 C 左边的小数字只能用×。

(5)D 和 M 左 边的小数字只能用 C 。

【分析】

(1)罗马数字转阿拉伯数字:

从前往后遍历罗马数字,如果某个数比前一个数小,则把该数加入到结果中;反之,则在结果中两次减去前一个数并加上当前这个数;

比如XVIII=18,是如何得到的?其对应的阿拉伯数字表示为10_5_1_1_1,因此结果为10+5+1+1+1=18;

XIX=19是如何得到的?其对应的阿拉伯数字表示为10_1_10,因此结果为10+1+10-2*1=19。

(2)阿拉伯数字转罗马数字:

把所有小数字在前的组合也作为基本数字,做一个对应的数值映射表。

比如4=1-5=IV,9=1-10=IX,40=10-50=XL,90=10-100=XC,400=100-500=CD, 900=100-1000=CM。

那么可以得到对应的映射为:

unsigned int val[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};

string r[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

对于阿拉伯数字n,遍历val数组,如果n>=val[i],则结果保留r[i],同时更新n=n-val[i],直到n=0为止。

【测试】

给定一个数字n,利用integer2raman函数转换为罗马数字r,然后再利用roman2integer函数将r转换为m,那么如果n!=m,则说明函数有问题。如果相等,则函数正确。

【代码】

C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//Roman2Integer.cpp:Definestheentrypointfortheconsoleapplication.
//
/*
version:1.0
author:hellogiser
blog:http://www.cnblogs.com/hellogiser
date:2014/5/26
*/

#include"stdafx.h"
#include<string>
#include<iostream>
#include<map>
#include<assert.h>
usingnamespacestd;

//romantointeger
unsignedintroman2integer(stringstr)
{
//99-->10,100,1,10
//66--->50,10,5,1
if(str=="")
return0;
map<char,int>m;
m['I']=1;
m['V']=5;
m['X']=10;
m['L']=50;
m['C']=100;
m['D']=500;
m['M']=1000;

intsum=m[str[0]];
intlen=str.length();
for(inti=0;i<len-1;i++)
{
if(m[str[i]]>=m[str[i+1]])
{
//m[i]>=m[i+1],thenaddm[i+1]tosum
sum=sum+m[str[i+1]];
}
else
{
//m[i]<m[i+1],thenaddm[i+1]tosum,andremove2*m[i]
sum=sum+m[str[i+1]]-2*m[str[i]];
}
}
returnsum;
}

#defineMAX3999

//integertoroman
stringinteger2roman(unsignedintn)
{
//weshouldconsider4,9,40,90,400,900
stringresult="";
if(n<1||n>MAX)
returnresult;

unsignedintval[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
unsignedintlength=sizeof(val)/sizeof(int);
stringr[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

for(inti=0;i<length;i++)
{
while(n>=val[i])
{
result+=r[i];
n-=val[i];
}
}
returnresult;
}

//testcasefortwofunctions
voidtest_case(intn)
{
for(inti=1;i<=n;i++)
{
stringroman=integer2roman(i);
intinteger=roman2integer(roman);
assert(i==integer);
}
}

voidtest_main()
{
//test_case(20);
test_case(MAX);
}

int_tmain(intargc,_TCHAR*argv[])
{
test_main();
return0;
}

上面给出了roman2integer和integer2roman的实现,并且对函数进行了测试。对于1到3999的数字n,求得其对应的罗马数字为r,再将r转换为阿拉伯数字m,那么n应该和m相等。因而test_case中的assert(i==integer);语句能够正常运行,而不抛出异常。



相关评论