🏛️ 羅馬數字轉換器完全指南
深入了解羅馬數字系統的歷史、轉換規則與演算法實作。從基礎符號到特殊情況處理, 掌握羅馬數字與阿拉伯數字互轉技巧,適用於歷史文獻、建築設計等應用場景。
1. 羅馬數字系統與歷史 🏛️
羅馬數字的起源
羅馬數字(Roman Numerals)起源於古羅馬,是一種使用拉丁字母來表示數字的系統。 與現代的阿拉伯數字(位值制)不同,羅馬數字採用累加減法制, 透過符號的組合與位置關係來表達數值。
💡 歷史背景
- 公元前 500 年:羅馬數字系統在古羅馬城邦形成
- 中世紀:歐洲廣泛使用於商業、建築、文獻記錄
- 14 世紀:阿拉伯數字引入歐洲,逐漸取代羅馬數字
- 現代:仍用於鐘錶、建築年份、書籍章節、電影片尾字幕等
基本符號與數值
羅馬數字使用 7 個基本符號,每個符號對應一個固定數值:
| 符號 | 數值 | 記憶技巧 |
|---|---|---|
I |
1 | 一根手指(I = 1) |
V |
5 | 手掌張開(V 形) |
X |
10 | 雙手交叉(X = 10) |
L |
50 | 拉丁文 Libra(50 磅) |
C |
100 | 拉丁文 Centum(100) |
D |
500 | 半個 M(1000 的一半) |
M |
1000 | 拉丁文 Mille(1000) |
羅馬數字的特點
✅ 優點
- 符號直觀,易於雕刻與書寫
- 不需要「零」的概念
- 小數值計算較快(如 I、II、III)
- 具有儀式感和歷史美感
❌ 局限性
- 無法表示零和負數
- 無法表示小數和分數
- 大數運算複雜(如乘除法)
- 符號組合規則較多,易出錯
2. 快速開始指南 🚀
選擇轉換方向
決定要將阿拉伯數字轉羅馬數字,還是羅馬數字轉阿拉伯數字。
- 阿拉伯 → 羅馬:
2024→MMXXIV - 羅馬 → 阿拉伯:
MCMXCIV→1994
輸入數字或符號
在輸入框中輸入要轉換的數字(1-3999)或羅馬數字符號。
驗證輸入合法性
系統會自動檢查輸入是否符合羅馬數字規則:
- ✅ 只包含合法符號(I, V, X, L, C, D, M)
- ✅ 符號組合符合減法規則(如 IV, IX, XL)
- ✅ 沒有超過 3 次連續重複(如 IIII 是錯誤的)
執行轉換
點擊「轉換」按鈕,系統會即時顯示轉換結果。
58→LVIII(L=50, V=5, III=3)CDXLIV→444(CD=400, XL=40, IV=4)
查看分解步驟
點擊「顯示步驟」可查看詳細的轉換過程和邏輯:
2024 的轉換步驟: 1. 2000 = MM(M×2) 2. 20 = XX(X×2) 3. 4 = IV(5-1) 結果:MMXXIV
3. 轉換規則與特殊情況 📐
基本規則:累加與減法
羅馬數字的核心規則是累加和減法:
🔹 規則 1:符號累加
當較大的符號在前,較小的符號在後時,進行累加。
VI= V + I = 5 + 1 = 6XII= X + I + I = 10 + 1 + 1 = 12LXV= L + X + V = 50 + 10 + 5 = 65
🔹 規則 2:減法記號
當較小的符號在前,較大的符號在後時,進行減法。
| 減法組合 | 數值 | 說明 |
|---|---|---|
IV |
4 | 5 - 1 = 4 |
IX |
9 | 10 - 1 = 9 |
XL |
40 | 50 - 10 = 40 |
XC |
90 | 100 - 10 = 90 |
CD |
400 | 500 - 100 = 400 |
CM |
900 | 1000 - 100 = 900 |
🔹 規則 3:重複限制
相同符號最多連續出現 3 次(V、L、D 不可重複)。
- ✅
III= 3(合法) - ❌
IIII= 4(錯誤,應寫作 IV) - ✅
XXX= 30(合法) - ❌
XXXX= 40(錯誤,應寫作 XL)
特殊情況處理
🔸 情況 1:減法只能用於特定組合
不是所有小符號都能放在大符號前面。只有以下組合合法:
I只能放在V和X前面(IV, IX)X只能放在L和C前面(XL, XC)C只能放在D和M前面(CD, CM)
IL(49)、IC(99)、XM(990)都是非法的!
✅ 正確寫法:49 = XLIX,99 = XCIX,990 = CMXC
🔸 情況 2:零和負數
羅馬數字系統沒有零的概念,也無法表示負數。
- 零:古羅馬用
nulla(拉丁文「無」)表示 - 負數:需要額外標註(如
-V表示 -5)
🔸 情況 3:大數表示(超過 3999)
標準羅馬數字只能表示 1-3999。更大的數需要使用上劃線(表示 ×1000):
V̅= 5,000(5 × 1000)X̅= 10,000(10 × 1000)L̅= 50,000(50 × 1000)
4. 演算法實作 💻
阿拉伯數字 → 羅馬數字(貪婪演算法)
轉換策略:使用貪婪演算法(Greedy Algorithm), 從最大的符號組合開始,依次減去對應數值,直到數字變為 0。
function toRoman(num) {
// 定義符號對照表(包含減法組合)
const mapping = [
{ value: 1000, symbol: 'M' },
{ value: 900, symbol: 'CM' }, // 減法組合
{ value: 500, symbol: 'D' },
{ value: 400, symbol: 'CD' }, // 減法組合
{ value: 100, symbol: 'C' },
{ value: 90, symbol: 'XC' }, // 減法組合
{ value: 50, symbol: 'L' },
{ value: 40, symbol: 'XL' }, // 減法組合
{ value: 10, symbol: 'X' },
{ value: 9, symbol: 'IX' }, // 減法組合
{ value: 5, symbol: 'V' },
{ value: 4, symbol: 'IV' }, // 減法組合
{ value: 1, symbol: 'I' }
];
let result = '';
// 貪婪匹配
for (const { value, symbol } of mapping) {
while (num >= value) {
result += symbol;
num -= value;
}
}
return result;
}
// 測試
console.log(toRoman(2024)); // 輸出: "MMXXIV"
console.log(toRoman(1994)); // 輸出: "MCMXCIV"
console.log(toRoman(444)); // 輸出: "CDXLIV"
⏱️ 時間複雜度分析
- 時間複雜度:O(1)(最多 13 次迴圈,常數時間)
- 空間複雜度:O(1)(固定大小的對照表)
- 優點:簡潔直觀,易於理解和維護
羅馬數字 → 阿拉伯數字(掃描演算法)
轉換策略:從左到右掃描符號,判斷當前符號與下一個符號的關係:
• 如果 current < next,減去當前值(減法規則)
• 否則,加上當前值(累加規則)
function fromRoman(roman) {
// 定義符號數值表
const values = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
};
let result = 0;
// 從左到右掃描
for (let i = 0; i < roman.length; i++) {
const current = values[roman[i]];
const next = values[roman[i + 1]];
// 減法規則:當前符號小於下一個符號
if (next && current < next) {
result -= current;
} else {
result += current;
}
}
return result;
}
// 測試
console.log(fromRoman('MMXXIV')); // 輸出: 2024
console.log(fromRoman('MCMXCIV')); // 輸出: 1994
console.log(fromRoman('CDXLIV')); // 輸出: 444
⏱️ 時間複雜度分析
- 時間複雜度:O(n)(n = 羅馬數字長度,最多 15 位)
- 空間複雜度:O(1)(固定大小的符號表)
- 優點:單次掃描,高效簡潔
轉換步驟可視化範例
以 1994 轉換為羅馬數字為例:
初始數字: 1994 步驟 1: 1994 >= 1000 → 加入 'M',剩餘 994 步驟 2: 994 >= 900 → 加入 'CM',剩餘 94 步驟 3: 94 >= 90 → 加入 'XC',剩餘 4 步驟 4: 4 >= 4 → 加入 'IV',剩餘 0 結果: MCMXCIV
5. 常見問題 ❓
Q1: 為什麼 4 寫作 IV 而不是 IIII?
這是減法記號的應用。IV(5-1=4)比 IIII 更簡潔。 但在某些古老鐘錶上,仍可見到 IIII 的寫法,這是為了視覺對稱性(與 VIII 對稱)。
古代變體:4 = IIII(鐘錶常見)
Q2: 羅馬數字能表示小數嗎?
標準羅馬數字無法表示小數。古羅馬使用分數系統(如 1/12 稱為 uncia), 但沒有類似現代小數點的概念。現代若需表示小數,通常使用阿拉伯數字。
Q3: 如何驗證羅馬數字是否合法?
使用正則表達式(Regex)進行驗證:
function isValidRoman(roman) {
// 正則表達式:匹配合法的羅馬數字(1-3999)
const regex = /^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/;
return regex.test(roman);
}
console.log(isValidRoman('MCMXCIV')); // true(合法)
console.log(isValidRoman('IIII')); // false(不合法)
console.log(isValidRoman('IC')); // false(不合法的減法組合)
Q4: 羅馬數字轉換器的實際用途有哪些?
現代應用場景包括:
- 🏛️ 建築設計:建築年份標記(如 MMXXIV = 2024)
- 📚 出版業:書籍章節編號、前言頁碼
- 🎬 影視業:電影片尾字幕年份(如 ©MMXXIV)
- ⏰ 鐘錶製造:高級手錶錶盤數字
- 🎓 學術研究:歷史文獻解讀、考古研究
Q5: 羅馬數字轉換有哪些常見錯誤?
初學者常見錯誤:
| 錯誤寫法 | 正確寫法 | 錯誤原因 |
|---|---|---|
IIII |
IV |
超過 3 次重複 |
VV |
X |
V 不可重複 |
IL |
XLIX |
非法減法組合 |
IC |
XCIX |
非法減法組合 |
6. 進階技巧與驗證邏輯 🔬
完整驗證系統
實作一個完整的羅馬數字驗證器,包含格式檢查、範圍驗證、規則檢查:
class RomanValidator {
constructor() {
this.validSymbols = /^[IVXLCDM]+$/;
this.validPattern = /^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/;
}
validate(roman) {
const errors = [];
// 1. 檢查空字串
if (!roman || roman.trim() === '') {
errors.push('輸入不能為空');
return { valid: false, errors };
}
// 2. 檢查大小寫(統一轉大寫)
roman = roman.toUpperCase();
// 3. 檢查是否包含非法字符
if (!this.validSymbols.test(roman)) {
errors.push('包含非法字符(只允許 I, V, X, L, C, D, M)');
}
// 4. 檢查組合規則
if (!this.validPattern.test(roman)) {
errors.push('符號組合不符合羅馬數字規則');
}
// 5. 檢查範圍(1-3999)
if (errors.length === 0) {
const value = this.fromRoman(roman);
if (value < 1 || value > 3999) {
errors.push(`數值超出範圍(1-3999),當前值:${value}`);
}
}
return {
valid: errors.length === 0,
errors: errors,
value: errors.length === 0 ? this.fromRoman(roman) : null
};
}
fromRoman(roman) {
const values = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 };
let result = 0;
for (let i = 0; i < roman.length; i++) {
const current = values[roman[i]];
const next = values[roman[i + 1]];
result += (next && current < next) ? -current : current;
}
return result;
}
}
// 測試驗證器
const validator = new RomanValidator();
console.log(validator.validate('MCMXCIV'));
// { valid: true, errors: [], value: 1994 }
console.log(validator.validate('IIII'));
// { valid: false, errors: ['符號組合不符合羅馬數字規則'], value: null }
console.log(validator.validate('IC'));
// { valid: false, errors: ['符號組合不符合羅馬數字規則'], value: null }
雙向轉換整合
將轉換和驗證整合到一個完整的工具類:
class RomanNumerals {
static toRoman(num) {
if (num < 1 || num > 3999) {
throw new Error('數字必須在 1-3999 範圍內');
}
const mapping = [
[1000, 'M'], [900, 'CM'], [500, 'D'], [400, 'CD'],
[100, 'C'], [90, 'XC'], [50, 'L'], [40, 'XL'],
[10, 'X'], [9, 'IX'], [5, 'V'], [4, 'IV'], [1, 'I']
];
let result = '';
for (const [value, symbol] of mapping) {
while (num >= value) {
result += symbol;
num -= value;
}
}
return result;
}
static fromRoman(roman) {
const validator = new RomanValidator();
const validation = validator.validate(roman);
if (!validation.valid) {
throw new Error(`無效的羅馬數字:${validation.errors.join(', ')}`);
}
return validation.value;
}
static isValid(roman) {
const validator = new RomanValidator();
return validator.validate(roman).valid;
}
}
// 使用範例
try {
console.log(RomanNumerals.toRoman(2024)); // "MMXXIV"
console.log(RomanNumerals.fromRoman('MCMXCIV')); // 1994
console.log(RomanNumerals.isValid('IV')); // true
console.log(RomanNumerals.isValid('IIII')); // false
} catch (error) {
console.error(error.message);
}
性能優化技巧
💡 快取結果
對於重複查詢,使用 Map 快取轉換結果:
const romanCache = new Map();
function toRomanCached(num) {
if (romanCache.has(num)) {
return romanCache.get(num);
}
const result = RomanNumerals.toRoman(num);
romanCache.set(num, result);
return result;
}
💡 批次轉換
一次處理多個數字,減少函數調用開銷:
function batchToRoman(numbers) {
return numbers.map(num => ({
decimal: num,
roman: RomanNumerals.toRoman(num)
}));
}
const results = batchToRoman([1, 4, 9, 50, 100, 500, 1000, 2024]);
console.log(results);
// [{ decimal: 1, roman: 'I' }, { decimal: 4, roman: 'IV' }, ...]
7. 實際應用案例 🎯
📚 案例 1:書籍章節自動編號
需求:自動為書籍章節生成羅馬數字編號(前言、目錄等使用羅馬數字)。
class BookChapterNumbering {
static generateFrontMatter(pages) {
const chapters = [];
for (let i = 1; i <= pages; i++) {
chapters.push({
page: i,
romanNumeral: RomanNumerals.toRoman(i),
section: '前言'
});
}
return chapters;
}
static generateTableOfContents(chapters) {
return chapters.map((title, index) => ({
chapter: `第 ${RomanNumerals.toRoman(index + 1)} 章`,
title: title
}));
}
}
// 生成前言頁碼(i, ii, iii, iv, v...)
const frontMatter = BookChapterNumbering.generateFrontMatter(10);
console.log(frontMatter);
// [{ page: 1, romanNumeral: 'I', section: '前言' }, ...]
// 生成章節目錄
const chapters = ['緒論', '文獻回顧', '研究方法', '結果與討論', '結論'];
const toc = BookChapterNumbering.generateTableOfContents(chapters);
console.log(toc);
// [{ chapter: '第 I 章', title: '緒論' }, { chapter: '第 II 章', title: '文獻回顧' }, ...]
🏛️ 案例 2:建築年份標記生成器
需求:為建築物、紀念碑生成羅馬數字年份標記(如 MMXXIV)。
class BuildingYearMarker {
static generateMarker(year, prefix = '©') {
if (year < 1 || year > 3999) {
throw new Error('年份必須在 1-3999 範圍內');
}
const romanYear = RomanNumerals.toRoman(year);
return `${prefix} ${romanYear}`;
}
static generatePeriodMarker(startYear, endYear) {
const start = RomanNumerals.toRoman(startYear);
const end = RomanNumerals.toRoman(endYear);
return `${start} - ${end}`;
}
}
// 生成當前年份標記
console.log(BuildingYearMarker.generateMarker(2024));
// "© MMXXIV"
// 生成時期標記(如羅馬帝國:27 BC - 476 AD)
console.log(BuildingYearMarker.generatePeriodMarker(27, 476));
// "XXVII - CDLXXVI"
🎬 案例 3:電影片尾字幕年份轉換
需求:批次轉換電影製作年份為羅馬數字(電影業標準格式)。
class MovieCreditGenerator {
static generateCopyright(year, company) {
const romanYear = RomanNumerals.toRoman(year);
return `© ${romanYear} ${company}. All Rights Reserved.`;
}
static batchGenerate(movies) {
return movies.map(movie => ({
...movie,
copyrightNotice: this.generateCopyright(movie.year, movie.studio)
}));
}
}
const movies = [
{ title: 'The Matrix', year: 1999, studio: 'Warner Bros.' },
{ title: 'Inception', year: 2010, studio: 'Warner Bros.' },
{ title: 'Interstellar', year: 2014, studio: 'Paramount Pictures' }
];
const credits = MovieCreditGenerator.batchGenerate(movies);
console.log(credits);
// [
// { title: 'The Matrix', year: 1999, studio: 'Warner Bros.',
// copyrightNotice: '© MCMXCIX Warner Bros. All Rights Reserved.' },
// ...
// ]
🚀 立即試用羅馬數字轉換器
體驗完整的羅馬數字轉換功能,支援雙向轉換、即時驗證、步驟分解。
立即使用工具