IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    罗马数字与阿拉伯数字相互转换 - RustFisher

    RustFisher发表于 2015-09-22 14:25:00
    love 0

    罗马数字规则简明

    1. 罗马单个数字共有7个,即I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)
    2.一个罗马数字重复几次,就表示这个数的几倍。但同一数码不能出现三次以上。
    3.遵循右加左减的规则。
    左减的数字有限制,仅限于I、X、C。比如45不可以写成VL,只能是XLV
    但是,左减时不可跨越一个位数。比如,99不可以用IC(100 - 1)表示,
    而是用XCIX([100 - 10] + [10 - 1])表示。(等同于阿拉伯数字每位数字分别表示。)
    左减数字必须为一位,比如8写成VIII,而非IIX。

     

    Roman to Int

    基本思路:把输入的罗马数字分段处理,分段相加。从左到右,一个个检测过去。
    设置 当前位current,上一位pre,分段值temp。
    如果当前位对应的值和上一位的一样(current == pre),那么分段值加上当前值{temp += current;}。比如III = 3
    如果当前位对应的值大于上一位的(current > pre),说明分段值应该是当前值减去现有的分段值{temp = current - temp;}。比如IIV = 5 – 2
    如果当前位对应的值小于上一位的(current < pre),那么可以先将当前分段值加到结果中,重新开始记录分段值{result += temp;temp = current;}。比如XI = 10 + 1

     

    Int to Roman


    思路是把数字拆成单独的部分,最后拼接起来

    1. 判断输入数字共有几位,digits
    2. 拆分数字,把每一位数字存入数组singleInt[i]中
    3. 把每位数字单独转换singleDigitToRoman成罗马数字,存入罗马数字数组singleRoman[i]中
    4. 最后拼接起来result.append(singleRoman[i])

    单独转换方法singleDigitToRoman(int n, int nth)接收2个参数,一个是输入数字,一个是当前数字的位数
    singleDigitToRoman方法中,把罗马数字单个存放在char数组里,方便调用
    char singleRoman[] = {'I','V','X','L','C','D','M','Z','E'}; // never use 'Z' & 'E'
    数组中'Z' 和 'E'都只是用来占位的,避免数组越界;正常情况下都不会出现
    根据输入数字n,分段判断;每段有不同的拼接方式


    假设输入数字的范围1~3999,以下是完整的Java代码

    1 /**
    2 * @author Rust Fisher
    3 * Reverse number to Roman or reverse Roman to number
    4 */
    5 public class RomanAndInt {
    6 /**
    7 * @param s - String Roman
    8 * @return int number
    9 */
    10 public static int romanToInt(String s) {
    11 if (s.length() < 1) return 0;
    12 int result = 0;
    13 int current = 0;
    14 int pre = singleRomanToInt(s.charAt(0));
    15 int temp = pre;
    16 for (int i = 1; i < s.length(); i++) {
    17 current = singleRomanToInt(s.charAt(i));
    18 if (current == pre)
    19 temp += current;
    20 else if (current > pre){
    21 temp = current - temp;
    22 }
    23 else if (current < pre){
    24 result += temp;
    25 temp = current;
    26 }
    27 pre = current;
    28 }
    29 result += temp;
    30 return result;
    31
    32 }
    33 /**
    34 * @param c single Roman
    35 * @return single number
    36 */
    37 public static int singleRomanToInt(char c){
    38 switch (c) {
    39 case 'I':
    40 return 1;
    41 case 'V':
    42 return 5;
    43 case 'X':
    44 return 10;
    45 case 'L':
    46 return 50;
    47 case 'C':
    48 return 100;
    49 case 'D':
    50 return 500;
    51 case 'M':
    52 return 1000;
    53 default:
    54 return 0;
    55 }
    56 }
    57 /**
    58 * @param n - input single int
    59 * @param nth must start from 1; 1 <= nth <= 4
    60 * @return String single Roman
    61 */
    62 public static String singleDigitToRoman(int n, int nth){
    63 if (n == 0) {
    64 return "";
    65 }
    66 nth = 2 * nth - 1; // nth must start from 1
    67 char singleRoman[] = {'I','V','X','L','C','D','M','Z','E'}; // never use 'Z' & 'E'
    68 StringBuilder rsb = new StringBuilder("");
    69 if (n <= 3) {
    70 for (int i = 0; i < n; i++) {
    71 rsb.append(singleRoman[nth-1]);
    72 }
    73 return rsb.toString();
    74 }
    75 if (n == 4) {
    76 rsb.append(singleRoman[nth-1]);
    77 rsb.append(singleRoman[nth]);
    78 return rsb.toString();
    79 }
    80 if (n == 5) {
    81 return singleRoman[nth] + "";
    82 }
    83 if (n >= 6 && n <= 8) {
    84 rsb.append(singleRoman[nth]);
    85 for (int i = 0; i < (n - 5); i++) {
    86 rsb.append(singleRoman[nth-1]);
    87 }
    88 return rsb.toString();
    89 }
    90 if (n == 9) {
    91 rsb.append(singleRoman[nth-1]);
    92 rsb.append(singleRoman[nth+1]);
    93 return rsb.toString();
    94 }
    95 return "ERROR!!!";
    96 }
    97 /**
    98 * @param num - input number within range 1 ~ 3999
    99 * @return String Roman number
    100 */
    101 public static String intToRoman(int num) {
    102 if (num < 1 || num > 3999) {
    103 return "ERROR input number is 1 ~ 3999";
    104 }
    105 int temp = num;
    106 String singleRoman[] = {"","","",""};
    107 StringBuilder result = new StringBuilder("");
    108 int digits = 0; // 1 ~ 4
    109 while (temp != 0){
    110 temp = temp/10;
    111 digits++;
    112 }
    113 temp = num;
    114 int[] singleInt = new int[digits];
    115 for (int i = 0; i < digits; i++) {
    116 singleInt[i] = temp%10;
    117 singleRoman[i] = singleDigitToRoman(temp%10,i+1);
    118 temp /= 10;
    119 }
    120 for (int i = digits-1; i >= 0; i--) {
    121 result.append(singleRoman[i]);
    122 }
    123 return result.toString();
    124 }
    125 /**
    126 * test main
    127 */
    128 public static void main(String args[]){
    129 for (int i = 0; i < 4; i++) {
    130 int input = (int) (Math.random()*Math.pow(10, i+1));
    131 if (input > 3999) {
    132 input = 3999;
    133 }
    134 System.out.println(input + " = " + intToRoman(input));
    135 }
    136 }
    137 }

     

    小结

    转换的思路在于截取数字,一位一位来处理,最后拼接或相加得到结果

    这两个过程都用到了处理单个数字的方法;化整为零,循环处理整个数字;把处理细节的方法封装起来,便于调用


    本文链接:罗马数字与阿拉伯数字相互转换,转载请注明。



沪ICP备19023445号-2号
友情链接