罗马数字和阿拉伯数字互化 java实现

本文介绍了罗马数字的计数规则,并探讨了如何使用Java实现罗马数字与阿拉伯数字之间的转换。针对阿拉伯数字转罗马数字,可以按10进制位数决定每位字符;罗马数字转阿拉伯数字则较为复杂,需要考虑字符组合的顺序避免歧义。文中提到的初步解决方案包括按位判断字符值,以及利用正则表达式的键值对方法,但后者因Map的遍历顺序问题需要使用字符串数组来确保正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们来看一下罗马数字的表数方法:
1.罗马数字采用七个罗马字母作数字、即Ⅰ(1)、X(10)、C(100)、M(1000)、V(5)、L(50)、D(500)
2.相同的数字连写,所表示的数等于这些数字相加得到的数,如 Ⅲ=3;
3.小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数,如 Ⅷ=8、Ⅻ=12;小的数字(限于 Ⅰ、X 和 C)在大的数字的左边,所表示的数等于大数减小数得到的数,如 Ⅳ=4、Ⅸ=9;
4.正常使用时、连写的数字重复不得超过三次;
5.在一个数的上面画一条横线、表示这个数扩大 1000 倍。

注意以下几个规则:
1.基本数字 Ⅰ、X 、C 中的任何一个、自身连用构成数目、或者放在大数的右边连用构成数目、都不能超过三个;放在大数的左边只能用一个;
2.不能把基本数字 V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目、只能使用一个;
3.I只能用在V和X左边;X只能用在L和C左边;C只能用在D和M左边。

首先我们可以想一想这样的计数体系的特点是什么。因为不能输出上划线所以讨论过大的数没有意义,那么不用上划线所能表示的最大的数是多少呢?没错你应该已经想到了MMMCMXCIX——3999。这种计数体系的倍数关系并不明显,而加数关系更加明显。比如369,先表示300——CCC,然后60——LX,然后9——IX。连起来就是CCCLXIX。……

 public static String ArabToRoman(int Arab){
     String Roman = "";
     String[][] list={
                {"","I","II","III","IV","V","VI","VII","VIII","IX"},
                {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"},
                {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"},
{"","M","MM","MMM","","","","","",""}
    };
    Roman += list[3][Arab/1000%10];
    Roman += list[2][Arab/100%10];
    Roman += list[1][Arab/10%10];
    Roman += list[0][Arab%10];
    return Roman;
}

阿拉伯数字转罗马数字主要就是按10进制位数决定每位字符就可以了。从罗马数字转阿拉伯数字就稍微繁琐一些,因为每个10进制位对应的字符串长度是不定的。我首先想到的是按位判断,每次判一个字符,然后加上相应的值,粗苯一些但是能工作:

public static int RomanToInt(String roman)
    int res=0;
    try {
        while(roman.charAt(0)=='M'){res+=1000;roman = roman.substring(1);}
        if(roman.charAt(0)=='D'){res+=500;roman = roman.substring(1);}
        while(roman.charAt(0)=='C'){res+=100;roman = roman.substring(1);}
        if(roman.charAt(0)=='D') {res+=300;roman = roman.substring(1);}
        else if(roman.charAt(0)=='M'){res+=800; roman = roman.substring(1);}
        if(roman.charAt(0)=='L'){res+=50;roman = roman.substring(1);}
        while(roman.charAt(0)=='X'){res+=10;roman=roman.substring(1);}
        if(roman.charAt(0)=='L'){res+=30;roman=roman.substring(1);}
        else if(roman.charAt(0)=='C'){res+=80;roman=roman.substring(1);}
        if(roman.charAt(0)=='V'){res+=5;roman=roman.substring(1);}
        while(roman.charAt(0)=='I'){res+=1;roman=roman.substring(1);}
        if(roman.charAt(0)=='V'){res+=3;roman=roman.substring(1);}
        else if(roman.charAt(0)=='X'){res+=8;roman= roman.substring(1);}
    } catch (StringIndexOutOfBoundsException e) {
            return res;
    }
    return res;
}

当字符串被截取成为了一个空串之后,再调用charAt(0)就会报错了,这个时候我们把它捕获,适时地返回已经得到的整数。
还有另外一个用到键值对和正则表达式的方法,马住下次再更。

———————————二更——————————

public static int RomanToInt3(String Roman){
    int res = 0;
    String regex=null;
    String s = "'',0,I,1,II,2,III,3,IV,4,V,5,VI,6,VII,7,VIII,8,IX,9,X,10,XX,20,XXX,30,XL,40,L,50,LX,60,LXX,70,LXXX,80,XC,90,C,100,CC,200,CCC,300,CD,400,D,500,DC,600,DCC,700,DCCC,800,CM,900,M,1000,MM,2000,MMM,3000";
    String c[]=s.split(",");//将字符串打散,存入数组s
    Pattern p;//正则
        //遍历循环,正则匹配
    for(int t=c.length-2;t>0;t-=2){
        String roma = c[t];
        int value = Integer.parseInt(c[t+1]);
        regex="^("+roma+")";      p=Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
        Matcher matcher=p.matcher(Roman);
        if(matcher.find()){
            res += value;
           Roman=Roman.substring(((String)roma).length());
//              System.out.print(Roman + "\t\t");
//              System.out.print(regex + "\t\t");
//              System.out.println(res);
        }
    }
    return res;
}

本来想用Map存储键值对,但是遍历Map中的元素用到的Iterator不是根据放入的键值对先后顺序进行遍历的,而是根据字母表顺序。也就是每次遍历时先找C,再找CC……这就很尴尬,因为CM的话是表示900,而Iterator会先找到C,再找到M,就变成了1100。所以我就直接用了一个字符串数组,从大到小遍历,这样从高位到地位是不会产生罗马数字歧义的。正则表达式确实是字符串处理的利器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值