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

来源:互联网 发布:日本留学融入 知乎 编辑:程序博客网 时间:2024/05/19 18:42

罗马数字规则简明

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 number100      */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 ~ 4109         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 main127      */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 }
复制代码

 

小结

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

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

0 0
原创粉丝点击