アラビア数字からローマ数字へ

1530 ワード

最初に考えたのは、進数回転として考えられていました.例えば、
1 -> I, 2 -> II, 5 -> V, 6 -> VI ....
public static String intToRoman1(int num) {
		
		String[] roman = {"I", "V", "X", "L", "C", "D", "M"};
		int[]    radix = { 1,   5,   10,  50, 100, 500, 1000};
		
		StringBuffer sb = new StringBuffer();
		for (int i = radix.length - 1; i >= 0; i--) {
			for (int j = num / radix[i]; j > 0; j--)
				sb.append(roman[i]);
			num = num % radix[i];
		}
		
		return sb.toString();
	}

しかしここには4対応のローマ数字がIIIではなくIVという穴があります
変更後:
public String intToRoman(int num) {
		String[] roman = {"", "", "I", "V", "X", "L", "C", "D", "M"};
		int[]    radix = { 0,  0,  1,   5,   10,  50, 100, 500, 1000};
		StringBuffer sb = new StringBuffer();
		for (int i = radix.length - 1; i >= 2 && num > 0; i--) {
			if (num + radix[(i - 2) + i % 2] >= radix[i]) {
				if (num >= radix[i]) {
					sb.append(roman[i]);
					num -= radix[i];
					i++;
				} else {
					sb.append(roman[(i - 2) + i % 2]).append(roman[i]);
					num = num + radix[(i - 2) + i % 2] - radix[i];
				}
				
			}
		}

ここでもう一つのピットは49が50−1ではなく(50−10)+(10−1)XLIXである
法則を探して発見する:
5,10は1,すなわちV,Xの前にIが1つしか減らない,
50100は10を減らすことしかできなくて、つまりL、Cの前は1つのXしかありません
5001000は100を減らすことしかできなくて、つまりD、Mの前は1つのCしかありません
num + radix[(i - 2) + i % 2]

このコードはこのピットを処理します