Roman 2.0.0

dotnet add package Roman --version 2.0.0
                    
NuGet\Install-Package Roman -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Roman" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Roman" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Roman" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Roman --version 2.0.0
                    
#r "nuget: Roman, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Roman@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Roman&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Roman&version=2.0.0
                    
Install as a Cake Tool

Roman

.NET C# NuGet License CodeOfConduct

A small, dependency-free C# library for Roman numerals: conversion to and from Arabic integers, arithmetic, and comparison. Immutable, allocation-light, and fully unit-tested.

🌐 Language: English Β· Русский

Table of contents

Features

  • Convert Arabic numbers (1–3999) to Roman and back
  • Arithmetic: addition, subtraction, multiplication, division
  • Comparison operators: >, <, >=, <=, ==, !=
  • Implements IComparable<Roman> and IEquatable<Roman>
  • Immutable type β€” every operation returns a new value
  • Well-defined null semantics in comparison operators
  • Case-insensitive parsing with surrounding whitespace trimmed
  • Strict (default) and lenient (RomanStyle.Lenient) parsing modes
  • TryParse for exception-free parsing
  • Allocation-light conversion via stackalloc Span<char>
  • No external dependencies

Installation

# .NET CLI
dotnet add package Roman
# Package Manager
Install-Package Roman

<PackageReference Include="Roman" Version="1.1.1" />

Quick start

using RomanNumerals;

// From an integer
var a = new Roman(42);
Console.WriteLine(a);            // XLII

// From a string
var b = new Roman("XIX");
Console.WriteLine(b.ToInt());    // 19

// Arithmetic
Console.WriteLine(a + b);        // LXI  (61)

// Comparison
if (a > b)
    Console.WriteLine("42 > 19");

// Exception-free parsing
if (Roman.TryParse("MCMXCIV", out var year))
    Console.WriteLine(year.ToInt());   // 1994

Note: the type is Roman, the namespace is RomanNumerals. Add using RomanNumerals; and use new Roman(...).

Usage

Creating values

var fromInt    = new Roman(1984);        // MCMLXXXIV
var fromString = new Roman("MMXXIII");   // 2023
var lower      = new Roman("  xlii  ");  // 42 (trimmed, case-insensitive)
var copy       = new Roman(fromInt);     // copy constructor

Conversions

// Parse β€” throws on invalid input
var r1 = Roman.Parse(500);
var r2 = Roman.Parse("D");

// TryParse β€” never throws
if (Roman.TryParse(42, out var r3)) { /* ... */ }
if (Roman.TryParse("invalid", out var r4)) { /* not reached */ }

// Implicit Roman -> int
int value = new Roman(42);     // 42

// Explicit int -> Roman (can throw)
var r5 = (Roman)99;            // XCIX

Arithmetic

Operations compute on the underlying integer and re-validate the result against the 1–3999 range, throwing OverflowException when the result overflows (> 3999) or underflows (< 1). Division is integer division.

new Roman(10) + new Roman(5);   // XV  (15)
new Roman(50) - new Roman(20);  // XXX (30)
new Roman(7)  * new Roman(8);   // LVI (56)
new Roman(20) / new Roman(4);   // V   (5)
new Roman(10) / new Roman(3);   // III (3, integer division)

new Roman(3999) + new Roman(1); // throws: result > 3999
new Roman(5)    - new Roman(5); // throws: result < 1

Comparison

var a = new Roman(50);
var b = new Roman(30);

a > b;            // true
a == b;           // false
a.CompareTo(b);   // > 0
a.Equals(b);      // false

null semantics mirror Comparer<T> (null sorts lowest):

Roman x = new Roman(5);
Roman y = null;

x > y;    // true   (a value is greater than null)
y < x;    // true   (null is less than any value)
x == y;   // false
x != y;   // true

Roman p = null, q = null;
p == q;   // true
p >= q;   // true

Parsing modes (strict / lenient)

By default parsing is strict β€” it accepts only the canonical form and rejects non-canonical input such as "IIII". This applies to the constructors, Parse(string) and TryParse(string, …):

new Roman("IV");    // OK -> 4
new Roman("IIII");  // FormatException: not canonical

For lenient parsing (accept non-canonical forms), pass RomanStyle.Lenient to the Parse / TryParse overloads β€” modeled after int.Parse(string, NumberStyles):

var roman = Roman.Parse("IIII", RomanStyle.Lenient);  // parses as 4
Console.WriteLine(roman);                              // IV (output is always canonical)

if (Roman.TryParse("IIII", RomanStyle.Lenient, out var r))
    Console.WriteLine(r);                              // IV

RomanStyle.Strict (the default) rejects garbage characters (ArgumentException), out-of-range values (ArgumentOutOfRangeException), and otherwise valid but non-canonical forms (FormatException).

Limitations

  • Range is 1–3999 (MMMCMXCIX). Values outside this range throw ArgumentOutOfRangeException. There is no representation for 0 or negatives.
  • Round-trip is value-preserving, not string-preserving. Roman.Parse("IIII", RomanStyle.Lenient).ToString() returns "IV". Strict parsing (the default) rejects non-canonical input outright.
  • Arithmetic results must stay within 1–3999, otherwise they throw.

API reference

Constructors

Constructor Description
Roman(int value) Creates a value from an integer (1–3999)
Roman(string roman) Creates a value from a string (strict)
Roman(Roman other) Copy constructor

Static methods

Method Description
Parse(int value) Parses an int; throws on error
Parse(string roman) Parses a string (strict); throws on error
Parse(string roman, RomanStyle style) Parses with a mode; Strict throws FormatException on non-canonical input
TryParse(int value, out Roman? result) Exception-free int parsing
TryParse(string roman, out Roman? result) Exception-free string parsing (strict)
TryParse(string roman, RomanStyle style, out Roman? result) Exception-free string parsing with a mode

Enums

RomanStyle Description
Strict Strict parsing (default): canonical form only
Lenient Lenient parsing: accepts non-canonical forms

Instance methods

Method Description
ToInt() Returns the Arabic value
ToString() Returns the canonical Roman string
CompareTo(Roman? other) Compares with another value
Equals(Roman? other) Value equality
GetHashCode() Hash code

Operators

Operator Description
+ - * / Arithmetic (integer division)
> < >= <= Comparison (null sorts lowest)
== != Equality
(int)roman Implicit conversion Roman -> int
(Roman)value Explicit conversion int -> Roman

Performance

The conversion path is allocation-light:

  • The int -> Roman conversion writes into a stackalloc Span<char> buffer β€” no heap allocation beyond the resulting string.
  • The type is immutable and wraps a single int, so instances are cheap to copy and compare.

Testing

The library ships with a comprehensive MSTest suite covering constructors, arithmetic, comparison, parsing (both modes), conversions, and int β†’ Roman β†’ string round-trips.

dotnet test                                   # run all tests
dotnet test --collect:"XPlat Code Coverage"   # with coverage

Contributing

Issues and pull requests are welcome. When filing a bug, please include the library version, the .NET version, a minimal reproduction, and the expected vs. actual behavior.

License

Licensed under the MIT License.

Author

deliciousNesquik β€” @deliciousNesquik

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 64 7/7/2026
1.1.1 82 6/17/2026
1.0.0 91 4/8/2026