package com.rc.components.study.arithmetic;
import org.junit.Test;
/**
* 羅馬數(shù)字
*
* 字符:
* 基本字符 I V X L C D M
* 阿拉伯?dāng)?shù)字 1 5 10 50 100 500 1000
*
* 計(jì)數(shù)方法:
* 1泥从、相同的數(shù)字連寫,所表示的數(shù)等于這些數(shù)字相加得到的數(shù)锭碳,如:Ⅲ = 3允悦;
* 2失受、小的數(shù)字在大的數(shù)字的右邊哎壳,所表示的數(shù)等于這些數(shù)字相加得到的數(shù)趴樱, 如:Ⅷ = 8醋奠;Ⅻ = 12;
* 3伊佃、小的數(shù)字,(限于Ⅰ沛善、X 和C)在大的數(shù)字的左邊航揉,所表示的數(shù)等于大數(shù)減小數(shù)得到的數(shù),如:Ⅳ= 4金刁;Ⅸ= 9帅涂;
* 4议薪、正常使用時(shí),連寫的數(shù)字重復(fù)不得超過三次媳友。(表盤上的四點(diǎn)鐘“IIII”例外)
* 5斯议、在一個(gè)數(shù)的上面畫一條橫線,表示這個(gè)數(shù)擴(kuò)大1000倍醇锚。
*
* 原則:
* 1哼御、基本數(shù)字Ⅰ、X 焊唬、C 中的任何一個(gè)恋昼,自身連用構(gòu)成數(shù)目,或者放在大數(shù)的右邊連用構(gòu)成數(shù)目赶促,都不能超過三個(gè)液肌;放在大數(shù)的左邊只能用一個(gè)。
* 2鸥滨、不能把基本數(shù)字V 嗦哆、L 、D 中的任何一個(gè)作為小數(shù)放在大數(shù)的左邊采用相減的方法構(gòu)成數(shù)目婿滓;放在大數(shù)的右邊采用相加的方式構(gòu)成數(shù)目老速,只能使用一個(gè)。
* 3空幻、V 和X 左邊的小數(shù)字只能用Ⅰ烁峭。
* 4、L 和C 左邊的小數(shù)字只能用X秕铛。
* 5约郁、D 和M 左邊的小數(shù)字只能用C。
*
* 示例:
* 個(gè)位數(shù)舉例Ⅰ,1 】Ⅱ但两,2】 Ⅲ鬓梅,3】 Ⅳ,4 】Ⅴ谨湘,5 】Ⅵ绽快,6】Ⅶ,7】 Ⅷ紧阔,8 】Ⅸ坊罢,9 】
* 十位數(shù)舉例Ⅹ,10】 Ⅺ擅耽,11 】Ⅻ活孩,12】 XIII,13】 XIV,14】 XV,15 】XVI,16 】XVII,17 】XVIII,18】 XIX,19】 XX,20】 XXI,21 】XXII,22 】XXIX,29】 XXX,30】 XXXIV,34】 XXXV,35 】XXXIX,39】 XL,40】 L,50 】LI,51】 LV,55】 LX,60】 LXV,65】 LXXX,80】 XC,90 】XCIII,93】 XCV,95 】XCVIII,98】 XCIX,99 】
* 百位數(shù)舉例C,100】 CC,200 】CCC,300 】CD,400】 D,500 】DC,600 】DCC,700】 DCCC,800 】CM,900】 CMXCIX,999】
* 千位數(shù)舉例M,1000】 MC,1100 】MCD,1400 】MD,1500 】MDC,1600 】MDCLXVI,1666】 MDCCCLXXXVIII,1888 】MDCCCXCIX,1899 】MCM,1900 】MCMLXXVI,1976】 MCMLXXXIV,1984】 MCMXC,1990 】MM,2000 】MMMCMXCIX,3999】
*
* @author: rc
* @date: 2018年3月3日 下午7:42:47
* @version: V1.0
* @review: rc/2018年3月3日 下午7:42:47
*/
public class RomanNumeral {
private final String stringValue;
private final int intValue;
public RomanNumeral(String romanStr){
this.stringValue = romanStr;
this.intValue = intValue(romanStr);
}
/**
* 獲取羅馬字符串
* @return
*/
public String stringValue() {
return stringValue;
}
/**
* 獲取阿拉伯?dāng)?shù)字值
* @return
*/
public int intValue() {
return intValue;
}
/**
* 羅馬數(shù)字轉(zhuǎn)阿拉伯?dāng)?shù)字
* @param romanStr
* @return
*/
public static int intValue(String romanStr){
if (romanStr.isEmpty()) {
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
int result = 0; //總數(shù)值
int repeatLength = 1; //一個(gè)字母連續(xù)重復(fù)出現(xiàn)的長度
int place = 0; //當(dāng)前已經(jīng)計(jì)算出的位數(shù)
char[] charArray = romanStr.toCharArray();
for (int i = charArray.length - 1; i >= 0; i--) { //從右往左遍歷
EBaseNumeral numeral =EBaseNumeral.build(charArray[i]);
if (numeral.getPlace() <= place) { //后面出現(xiàn)的字符位數(shù)應(yīng)該大于前面已經(jīng)確定了的最大位數(shù)
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
if (i == 0) { //只剩下最后一個(gè)字符時(shí),直接加上結(jié)果值乖仇,計(jì)算完成
place = numeral.getPlace(); //進(jìn)位
result += numeral.getN();
break;
}
EBaseNumeral numeralAfter = EBaseNumeral.build(charArray[i-1]); //獲取下一個(gè)字符
if (!numeral.isRepeatable()) { //5開頭的數(shù)字
if (numeral.equals(numeralAfter)) { //下一個(gè)字符相同
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
} else if (numeral.getPlace() < numeralAfter.getPlace()) { //下一個(gè)字符的位數(shù)大
place = numeral.getPlace(); //進(jìn)位
result += numeral.getN();
} else if (numeral.getPlace() == numeralAfter.getPlace()) { //下一個(gè)字符的位數(shù)不變并且是1開頭的數(shù)字
place = numeral.getPlace(); //進(jìn)位
result += numeral.getN() - numeralAfter.getN();
i--;
} else { //其他情況均非法
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
} else { //1字開頭
if (numeral.equals(numeralAfter)) { //下一個(gè)字符相同
if (repeatLength >= 3) { //字符連續(xù)出現(xiàn)次數(shù)超過3次
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
repeatLength++;
result += numeral.getN();
continue;
} else if (numeral.getPlace() < numeralAfter.getPlace()){ //下一個(gè)字符的位數(shù)大
place = numeral.getPlace(); //進(jìn)位
repeatLength = 0;
result += numeral.getN();
} else if (numeral.getPlace() == numeralAfter.getPlace()) { //下一個(gè)字符的位數(shù)不變并且是5開頭的數(shù)字
place = numeral.getPlace(); //進(jìn)位
repeatLength = 0;
result += numeral.getN() + numeralAfter.getN();
i--;
} else if (numeral.getPlace() > numeralAfter.getPlace() && numeral.getN() == numeralAfter.getN() *10) { //下一個(gè)字符位數(shù)變10倍的變小
place = numeralAfter.getPlace(); //進(jìn)位
repeatLength = 0;
result += numeral.getN() - numeralAfter.getN();
i--;
} else {
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
}
}
return result;
}
/**
* @param intNumeral 只支持1-3999的數(shù)字轉(zhuǎn)換
* @return
*/
public static String stringValue(int numberal){
if (numberal < 1 || numberal > 3999) {
throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
int baseNumberal = 0; //當(dāng)前位的數(shù)字
int place = 1; //位數(shù)
String stringValue = "";
while (numberal > 0) {
baseNumberal = numberal % 10; // 獲取位數(shù)
switch (baseNumberal * place) {
case 0: break;
case 1: stringValue = "I" + stringValue; break;
case 2: stringValue = "II" + stringValue; break;
case 3: stringValue = "III" + stringValue; break;
case 4: stringValue = "IV" + stringValue; break;
case 5: stringValue = "V" + stringValue; break;
case 6: stringValue = "VI" + stringValue; break;
case 7: stringValue = "VII" + stringValue; break;
case 8: stringValue = "VIII" + stringValue; break;
case 9: stringValue = "IX" + stringValue; break;
case 10: stringValue = "X" + stringValue; break;
case 20: stringValue = "XX" + stringValue; break;
case 30: stringValue = "XXX" + stringValue; break;
case 40: stringValue = "XL" + stringValue; break;
case 50: stringValue = "L" + stringValue; break;
case 60: stringValue = "LX" + stringValue; break;
case 70: stringValue = "LXX" + stringValue; break;
case 80: stringValue = "LXXX" + stringValue; break;
case 90: stringValue = "XC" + stringValue; break;
case 100: stringValue = "C" + stringValue; break;
case 200: stringValue = "CC" + stringValue; break;
case 300: stringValue = "CCC" + stringValue; break;
case 400: stringValue = "CD" + stringValue; break;
case 500: stringValue = "D" + stringValue; break;
case 600: stringValue = "DC" + stringValue; break;
case 700: stringValue = "DCC" + stringValue; break;
case 800: stringValue = "DCCC" + stringValue; break;
case 900: stringValue = "CM" + stringValue; break;
case 1000: stringValue = "M" + stringValue; break;
case 2000: stringValue = "MM" + stringValue; break;
case 3000: stringValue = "MMM" + stringValue; break;
default: throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
numberal /= 10;
place *= 10;
}
return stringValue;
}
//羅馬數(shù)字基本字符
private enum EBaseNumeral{
I('I',1,1,true),
V('V',5,1,false),
X('X',10,2,true),
L('L',50,2,false),
C('C',100,3,true),
D('D',500,3,false),
M('M',1000,4,true),
;
char c; //羅馬字符
int n; //對應(yīng)的阿拉伯?dāng)?shù)值
int place; //所在的位數(shù):1表示個(gè)位憾儒,2表示10位询兴,3表示百位,4表示千位
boolean repeatable; //當(dāng)前字符可否連續(xù)多次出現(xiàn)起趾,只有IXCM可以連續(xù)多次出現(xiàn)诗舰,VLD只能出現(xiàn)一次,即5開頭的數(shù)字
EBaseNumeral(char c, int n, int place, boolean repeatable){
this.c = c;
this.n = n;
this.place = place;
this.repeatable = repeatable;
}
public char getC() {
return c;
}
public int getN() {
return n;
}
public int getPlace() {
return place;
}
public boolean isRepeatable() {
return repeatable;
}
public static EBaseNumeral build(char c){
switch (c) {
case 'I': return I;
case 'V': return V;
case 'X': return X;
case 'L': return L;
case 'C': return C;
case 'D': return D;
case 'M': return M;
default: throw new IllegalArgumentException("非法的羅馬數(shù)字格式");
}
}
}
@Test
public static void test(){
int i = 0;
while (i++ < 3999) {
System.out.print("numberal=" + i);
String s = null;
try {
s = stringValue(i);
System.out.print(", stringValue()=" + s);
} catch (Exception e) {
System.out.print(", stringValue()=" + e.getMessage());
}
try {
int n = intValue(s);
System.out.print(", intValue()=" + n);
} catch (Exception e) {
System.out.print(", intValue()=" + e.getMessage());
}
System.out.println();
}
}
public static void main(String[] args) {
test();
}
}
羅馬數(shù)字轉(zhuǎn)換工具-java
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門钳恕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來别伏,“玉大人,你說我怎么就攤上這事忧额±灏梗” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵睦番,是天一觀的道長类茂。 經(jīng)常有香客問我,道長托嚣,這世上最難降的妖魔是什么巩检? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮示启,結(jié)果婚禮上兢哭,老公的妹妹穿的比我還像新娘。我一直安慰自己夫嗓,他們只是感情好迟螺,可當(dāng)我...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著舍咖,像睡著了一般矩父。 火紅的嫁衣襯著肌膚如雪贸桶。 梳的紋絲不亂的頭發(fā)上蚀瘸,一...
- 文/蒼蘭香墨 我猛地睜開眼辙售,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了飞涂?” 一聲冷哼從身側(cè)響起旦部,我...
- 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎较店,沒想到半個(gè)月后士八,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡梁呈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年婚度,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片官卡。...
- 正文 年R本政府宣布毛秘,位于F島的核電站饭寺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏叫挟。R本人自食惡果不足惜艰匙,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霞揉。 院中可真熱鬧旬薯,春花似錦、人聲如沸适秩。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽秽荞。三九已至骤公,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扬跋,已是汗流浹背阶捆。 一陣腳步聲響...
- 正文 我出身青樓倍奢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親垒棋。 傳聞我的和親對象是個(gè)殘疾皇子卒煞,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- //將中文(如'三百二十一')轉(zhuǎn)化成數(shù)字(321) + (NSString*)convertChineseToNu...
- 昨日,在 FCC 平臺(tái)整整用了兩三小時(shí)叼架,才刷出一道 JS 算法題畔裕,回首而看,最終的代碼也就那么多行乖订,記錄過程扮饶,寫文...
- 問題: 將給定的數(shù)字轉(zhuǎn)換成羅馬數(shù)字。 所有返回的羅馬數(shù)字都應(yīng)該是大寫形式乍构。 代碼: function conver...