How to Convert Roman Numerals to Decimal in Batch Script
Roman numerals (I, V, X, L, C, D, M) are still widely used in formal documents, clock faces, book chapters, and legal numbering. Converting a Roman numeral string like MCMXCIV into its decimal equivalent (1994) requires a specific parsing rule: if a smaller value appears before a larger value, it is subtracted rather than added (e.g., IV = 4, not 6).
In this guide, we will demonstrate how to parse and convert Roman numerals to decimal using a character-by-character scan.
The Strategy: The Look-Ahead Rule​
- Map each Roman character to its value (I=1, V=5, X=10, etc.).
- Scan the string from left to right.
- If the current value is less than the next value, subtract it (e.g.,
IVmeans $5 - 1 = 4$). - Otherwise, add it.
Implementation Script​
@echo off
setlocal enabledelayedexpansion
set /p "roman=Enter Roman numeral: "
:: Normalize to uppercase (Batch variables are case-insensitive, but this helps display)
set "input=!roman!"
for %%A in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
set "input=!input:%%A=%%A!"
)
:: 1. Define Value Map
set "V_I=1"
set "V_V=5"
set "V_X=10"
set "V_L=50"
set "V_C=100"
set "V_D=500"
set "V_M=1000"
:: 2. Initialize
set /a total=0
set /a idx=0
:: Get the length
set /a len=0
set "tmp=!input!"
:len_loop
if defined tmp (
set "tmp=!tmp:~1!"
set /a "len+=1"
goto :len_loop
)
:: 3. The Parsing Loop
:parse_loop
if !idx! GEQ !len! goto :show_result
:: Resolve current character and its value using for-loop resolution
for %%I in (!idx!) do set "ch=!input:~%%I,1!"
for %%C in (!ch!) do set "currVal=!V_%%C!"
:: Basic validation
if "!currVal!"=="" (
echo [ERROR] Invalid Roman numeral character: "!ch!"
pause & exit /b 1
)
:: Look ahead to next character for subtraction logic (e.g. IV)
set /a "nextIdx=idx+1"
set "nextVal=0"
if !nextIdx! LSS !len! (
for %%I in (!nextIdx!) do set "nch=!input:~%%I,1!"
for %%C in (!nch!) do set "nextVal=!V_%%C!"
)
:: Apply Roman subtraction rules
if !currVal! LSS !nextVal! (
set /a total-=currVal
) else (
set /a total+=currVal
)
set /a "idx+=1"
goto :parse_loop
:show_result
echo.
echo ==========================================
echo ROMAN: !input!
echo DECIMAL: !total!
echo ==========================================
pause
The “look-ahead” rule is implemented by reading the current character’s value (curr) and the next character’s value (next). If curr < next, the current value is subtracted; otherwise it is added. This correctly handles pairs like IV, IX, XL, CM, etc.
Why Convert Roman Numerals?​
- Document Parsing: If you scan through a legal document's table of contents (I, II, III, IV), you might need to convert those chapter numbers to integers for indexing or sorting.
- Historical Data: Dates on old manuscripts or government cornerstones are often in Roman numerals. Converting them allows for mathematical date comparison.
- Educational Tools: Building a Roman-to-Decimal converter is a great way to demonstrate lookup tables and conditional logic in Batch.
Important Considerations​
- Case Sensitivity: Batch variables are case-insensitive, but the lookup keys (
V_I,V_V, etc.) assume uppercase Roman characters. This guide normalizes input to uppercase before parsing. - Invalid Input: This script does not fully validate that the input is a properly formed Roman numeral. For example,
IIIIwill be accepted (yielding 4), even though the conventional form isIV. - Maximum Value: The largest standard Roman numeral is
MMMCMXCIX(3999). Values above this require a non-standard bar notation.
User input obtained via set /p is inherently untrusted. Always validate input if this will be used in automation. At minimum, this script includes a guard that detects unknown characters and stops before a set /a operation can fail.
Avoid mixing percent expansion (%idx%, %len%) with delayed expansion in loops. Percent expansion is evaluated when the block is parsed, which can produce wrong indices and broken substring extraction. This guide uses !idx!/!len! for comparisons and carefully uses delayed expansion for values that change inside loops.
Conclusion​
Converting Roman numerals to decimal numbers is a rewarding exercise in conditional logic and lookup-table design. By implementing the "Look-Ahead Subtraction" rule, you build a parser that can translate an ancient numbering system into modern integers. This technique demonstrates the power of Batch variable mapping and conditional arithmetic, providing a foundation for building text parsers and format converters of any complexity.