pysnippets.numbers.to_roman_numeral
Convert an integer to Roman numerals
to_roman_numeral(number: int) -> str
Convert 1 to 3999 into Roman numerals with a greedy table, rejecting values outside that range.
Chapter numbers, clock faces, movie sequels.
to_roman_numeral.py✓ ruff · mypy --strict
NUMERALS = [
(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"),
] # fmt: skip
def to_roman_numeral(number: int) -> str:
"""Convert an integer from 1 to 3999 to a Roman numeral."""
if not 1 <= number <= 3999:
raise ValueError(f"Roman numerals cover 1 to 3999, got {number}")
parts = []
for value, numeral in NUMERALS:
count, number = divmod(number, value)
parts.append(numeral * count)
return "".join(parts)- how many times this numeral fits, and what's left over
examples✓ 3 doctests · 3.11–3.14
passed on Python 3.11 to 3.14: >>> to_roman_numeral(11)'XI'passed on Python 3.11 to 3.14: >>> to_roman_numeral(1998)'MCMXCVIII'passed on Python 3.11 to 3.14: >>> to_roman_numeral(0)Traceback (most recent call last):...ValueError: Roman numerals cover 1 to 3999, got 0Edit the function or the examples and run the doctests here, on Python 3.14. Python loads only when you click (about 7 MB, cached after the first time).
python 3.14 · in your browser
Loading Python 3.14 in your browser (≈7 MB, cached after the first time)…
Tab inserts four spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the examples.
How it works
- The table lists every value with its numeral, largest first, including the subtractive pairs like 900 = CM.
divmodsays how many times each value fits and what’s left over.- Standard Roman numerals have no zero and stop at 3999, so anything else raises.
Complexity: O(1) time: at most 13 steps
- 3.11✓passes
- 3.12✓passes
- 3.13✓passes
- 3.14✓passes
Import
from pysnippets.numbers.to_roman_numeral import to_roman_numeralNo dependencies: copy to_roman_numeral.py into your project, or clone the repo.Adapted from to-roman-numeral in 30-seconds-of-python by the 30 seconds of code contributors, CC BY 4.0. Changed: Validates the range; builds the result with join; typed. Suggest an edit.