Skip to main content
removed boilerplate...
Source Link
Jesse C. Slicer
  • 20.2k
  • 5
  • 74
  • 91
// <copyright file="RomanNumeralExtensions.cs" company="Always Elucidated Solution Pioneers, LLC">
// Copyright (c) 2008 Always Elucidated Solution Pioneers, LLC.  All Rights Reserved.
// </copyright>
// <author>Jesse C. Slicer</author>
// <email>[email protected]</email>
// <date>2008-10-01</date>
// <summary>Translates Roman numeral strings to integers and vice-versa.</summary>
    
namespace Aesop.Extensions
{
    // System namespaces
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// Holds the IsValidRomanNumeral(), ParseRomanNumeral() and ToRomanNumeralString() extension methods.
    /// </summary>
    public static class RomanNumeralExtensions
    {
        /// <summary>
        /// The number of mappings in the dictionary.
        /// </summary>
        private const int NumberOfRomanNumeralMaps = 13;

        /// <summary>
        /// The matching of Roman numeral placeholders to their integer equivalents.
        /// </summary>
        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        /// <summary>
        /// The regular expression to test the string against.
        /// </summary>
        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        /// <summary>
        /// Determines whether the specified string is a valid Roman numeral.
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string to validate.
        /// </param>
        /// <returns>
        /// <c>true</c> if the specified string is a valid Roman numeral; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        /// <summary>
        /// Parses the Roman numeral into its integer equivalent.
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string.
        /// </param>
        /// <returns>
        /// The integer representation of the Roman numeral.
        /// </returns>
        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        /// <summary>
        /// Converts the number to its equivalent Roman numeral string.
        /// </summary>
        /// <param name="value">
        /// The integer to convert.
        /// </param>
        /// <returns>
        /// The Roman numeral representation of the integer.
        /// </returns>
        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }

     }
}
// <copyright file="RomanNumeralExtensions.cs" company="Always Elucidated Solution Pioneers, LLC">
// Copyright (c) 2008 Always Elucidated Solution Pioneers, LLC.  All Rights Reserved.
// </copyright>
// <author>Jesse C. Slicer</author>
// <email>[email protected]</email>
// <date>2008-10-01</date>
// <summary>Translates Roman numeral strings to integers and vice-versa.</summary>
    
namespace Aesop.Extensions
{
    // System namespaces
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// Holds the IsValidRomanNumeral(), ParseRomanNumeral() and ToRomanNumeralString() extension methods.
    /// </summary>
    public static class RomanNumeralExtensions
    {
        /// <summary>
        /// The number of mappings in the dictionary.
        /// </summary>
        private const int NumberOfRomanNumeralMaps = 13;

        /// <summary>
        /// The matching of Roman numeral placeholders to their integer equivalents.
        /// </summary>
        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        /// <summary>
        /// The regular expression to test the string against.
        /// </summary>
        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        /// <summary>
        /// Determines whether the specified string is a valid Roman numeral.
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string to validate.
        /// </param>
        /// <returns>
        /// <c>true</c> if the specified string is a valid Roman numeral; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        /// <summary>
        /// Parses the Roman numeral into its integer equivalent.
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string.
        /// </param>
        /// <returns>
        /// The integer representation of the Roman numeral.
        /// </returns>
        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        /// <summary>
        /// Converts the number to its equivalent Roman numeral string.
        /// </summary>
        /// <param name="value">
        /// The integer to convert.
        /// </param>
        /// <returns>
        /// The Roman numeral representation of the integer.
        /// </returns>
        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }

     }
}
    public static class RomanNumeralExtensions
    {
        private const int NumberOfRomanNumeralMaps = 13;

        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }
    }
removed ghastly code formatting from a previous job.
Source Link
Jesse C. Slicer
  • 20.2k
  • 5
  • 74
  • 91

Here's a to-and-from for Roman Numeralsnumerals. Not often used, but could be handy. Usage:

if ("IV".IsValidRomanNumeral ())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine ("MMMDCCCLXXXVIII".ParseRomanNumeral ());
Console.WriteLine (3888.ToRomanNumeralString ());
// <copyright file="RomanNumeralExtensions.cs" company="Always Elucidated Solution Pioneers, LLC">
// Copyright (c) 2008 Always Elucidated Solution Pioneers, LLC.  All Rights Reserved.
// </copyright>
// <author>Jesse C. Slicer</author>
// <email>[email protected]</email>
// <date>2008-10-01</date>
// <summary>Translates Roman Numeralnumeral strings to integers and vice-versa.</summary>
    
namespace Aesop.Extensions
{
#region Using Directives

  // System namespaces
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;

#endregion

#region Static Class Definition : RomanNumeralExtensions

    /// <summary>
    ///   Holds the IsValidRomanNumeral (), ParseRomanNumeral () and
///   ToRomanNumeralString () extension methods.
    /// </summary>
    public static class RomanNumeralExtensions
    {
   #region Public Static Extension Methods /// <summary>
        /// The number of mappings in the dictionary.
        /// </summary>
        private const int NumberOfRomanNumeralMaps = 13;

        /// <summary>
        ///   DeterminesThe whethermatching theof specifiedRoman stringnumeral isplaceholders ato validtheir Romaninteger numeralequivalents.
        /// </summary>
   /// <param name="value">   private static readonly Dictionary<string, int> romanNumerals =
   ///   The Roman numeral string to validate. new Dictionary<string, int>(NumberOfRomanNumeralMaps)
   /// </param>        {
   /// <returns>            { "M", 1000 }, 
   ///   <c>true</c> if the specified string is a valid Roman numeral; { "CM", 900 }, 
   ///   otherwise          { "D", <c>false</c>.500 }, 
   /// </returns>            { "CD", 400 }, 
   public static bool           { "C", 100 }, 
   IsValidRomanNumeral (this string value)          { "XC", 90 }, 
                { "L", 50 }, 
      return m_validRomanNumeral.IsMatch (value);        { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

   /// <summary>
    ///   Parses the Roman<summary>
 numeral into its integer equivalent.
   /// </summary>
 The regular ///expression <paramto name="value">
test the string ///against.
   The Roman numeral string.
   /// </param>summary>
   /// <returns>
   ///  private Thestatic integerreadonly representationRegex ofvalidRomanNumeral the= Romannew numeral.Regex(
   /// </returns>
   public static int
   ParseRomanNumeral "^(this string value?i:(?=[MDCLXVI])
   ((M{0,3})((C[DM])|(D?C{0,3}))"
      if (value == null)
     + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
         throw new ArgumentNullException ("value"RegexOptions.Compiled);
      }

      value = value/// <summary>
        /// Determines whether the specified string is a valid Roman numeral.ToUpperInvariant
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string to validate.
        /// </param>
        /// <returns>
        /// <c>true</c> if the specified string is a valid Roman numeral; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsValidRomanNumeral(this string value).Trim
        {
            return validRomanNumeral.IsMatch(value);
        }

      var  length/// =<summary>
 value       /// Parses the Roman numeral into its integer equivalent.Length;
        /// </summary>
      if ((length ==/// 0)<param ||name="value">
 !value       /// The Roman numeral string.IsValidRomanNumeral
        /// </param>
        /// <returns>
        /// The integer representation of the Roman numeral.
        /// </returns>
        public static int ParseRomanNumeral()this string value)
        {
         throw new ArgumentException if (value == null)
            "Empty{
 or invalid Roman numeral string.",
           throw new ArgumentNullException("value");
            }

      var  total = 0;
      var  ivalue = length;
      
      while value.ToUpperInvariant(i > 0)
      {
         var  digit = m_romanNumerals [value [--i].ToString Trim()];;

         if (i > 0)
         {
            var  previousDigitlength = m_romanNumerals [value [i - 1]value.ToString ()];Length;

            if (previousDigit(length <== digit0) || !value.IsValidRomanNumeral())
            {
               digit -= previousDigit;
       throw new ArgumentException("Empty or invalid Roman numeral string.", i--"value");
            }
         }

         total += digit;
      }

      return total;
   }

   /// <summary>
   ///   Converts the number to its equivalent Roman numeral string.
   /// </summary>
   /// <param name="value">
   ///   The integer to convert.
   /// </param>
   /// <returns>
   ///   The Roman numeral representation of the integer.
   /// </returns>
   public static string
   ToRomanNumeralStringvar (thistotal int= value)0;
   {
      const int  MinValue = 1;
      const int var MaxValuei = 3999;length;

      if ((value < MinValue) ||  while (valuei > MaxValue)0)
      {
         throw new ArgumentOutOfRangeException (
            "value",{
            value,
            "Argument out ofvar Romandigit numeral= rangeromanNumerals[value[--i]."ToString();
      }];

      const int  MaxRomanNumeralLength = 15;     if (i > 0)
      var        sb  {
                    var previousDigit = newromanNumerals[value[i StringBuilder- 1].ToString(MaxRomanNumeralLength);];

      foreach (var  pair in m_romanNumerals         if (previousDigit < digit)
                    {
         while (value / pair.Value > 0)
         { digit -= previousDigit;
            sb.Append (pair.Key)           i--;
            value -= pair.Value;      }
         }
       }

      return sb.ToString ();        total += digit;
            }

   #endregion         return total;
        }

   #region Private Static Member Data /// <summary>
        /// Converts the number to its equivalent Roman numeral string.
        /// </summary>
        /// <param name="value">
        /// The integer to convert.
        /// </param>
        /// <returns>
        /// The Roman numeral representation of the integer.
        /// </returns>
        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

   /// <summary>
   ///   The number ofif mappings((value in< theMinValue) dictionary.|| (value > MaxValue))
   /// </summary>
   private const int   {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
    NumberOfRomanNumeralMaps = 13;      }

   /// <summary>
   ///   The regular expression to test the string against.
const int MaxRomanNumeralLength ///= </summary>15;
   private static readonly Regex                   var m_validRomanNumeralsb =
      new Regex (
         "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
         + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?StringBuilder(II{0,2}))|V)?))$",
         RegexOptions.CompiledMaxRomanNumeralLength);

   /// <summary>
   ///   The matching of Roman numeral placeholders to their integer
  foreach ///(var pair in equivalents.romanNumerals)
   /// </summary>
   private static readonly Dictionary<string, int>  m_romanNumerals ={
      new Dictionary<string, int> (NumberOfRomanNumeralMaps)
   {
    while (value {/ "M",pair.Value 1000> },0)
      { "CM", 900 },
      { "D", 500 },
      { "CD", 400 },
      { "C", 100 },
      { "XC", 90 },
      { "L", 50 },sb.Append(pair.Key);
      { "XL", 40 },
      { "X", 10 },
      { "IX",value 9-= },pair.Value;
      { "V", 5 },
      { "IV", 4 },
      { "I", 1 }
   };

   #endregion         return sb.ToString();
        }

#endregion    }
}

Here's a to-and-from for Roman Numerals. Not often used, but could be handy. Usage:

if ("IV".IsValidRomanNumeral ())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine ("MMMDCCCLXXXVIII".ParseRomanNumeral ());
Console.WriteLine (3888.ToRomanNumeralString ());
// <copyright file="RomanNumeralExtensions.cs" company="Always Elucidated Solution Pioneers, LLC">
// Copyright (c) 2008 Always Elucidated Solution Pioneers, LLC.  All Rights Reserved.
// </copyright>
// <author>Jesse C. Slicer</author>
// <email>[email protected]</email>
// <date>2008-10-01</date>
// <summary>Translates Roman Numeral strings to integers and vice-versa.</summary>

namespace Aesop.Extensions
{
#region Using Directives

// System namespaces
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

#endregion

#region Static Class Definition : RomanNumeralExtensions

/// <summary>
///   Holds the IsValidRomanNumeral (), ParseRomanNumeral () and
///   ToRomanNumeralString () extension methods.
/// </summary>
public static class RomanNumeralExtensions
{
   #region Public Static Extension Methods

   /// <summary>
   ///   Determines whether the specified string is a valid Roman numeral.
   /// </summary>
   /// <param name="value">
   ///   The Roman numeral string to validate.
   /// </param>
   /// <returns>
   ///   <c>true</c> if the specified string is a valid Roman numeral;
   ///   otherwise, <c>false</c>.
   /// </returns>
   public static bool
   IsValidRomanNumeral (this string value)
   {
      return m_validRomanNumeral.IsMatch (value);
   }

   /// <summary>
   ///   Parses the Roman numeral into its integer equivalent.
   /// </summary>
   /// <param name="value">
   ///   The Roman numeral string.
   /// </param>
   /// <returns>
   ///   The integer representation of the Roman numeral.
   /// </returns>
   public static int
   ParseRomanNumeral (this string value)
   {
      if (value == null)
      {
         throw new ArgumentNullException ("value");
      }

      value = value.ToUpperInvariant ().Trim ();

      var  length = value.Length;
      
      if ((length == 0) || !value.IsValidRomanNumeral ())
      {
         throw new ArgumentException (
            "Empty or invalid Roman numeral string.",
            "value");
      }

      var  total = 0;
      var  i = length;
      
      while (i > 0)
      {
         var  digit = m_romanNumerals [value [--i].ToString ()];

         if (i > 0)
         {
            var  previousDigit = m_romanNumerals [value [i - 1].ToString ()];

            if (previousDigit < digit)
            {
               digit -= previousDigit;
               i--;
            }
         }

         total += digit;
      }

      return total;
   }

   /// <summary>
   ///   Converts the number to its equivalent Roman numeral string.
   /// </summary>
   /// <param name="value">
   ///   The integer to convert.
   /// </param>
   /// <returns>
   ///   The Roman numeral representation of the integer.
   /// </returns>
   public static string
   ToRomanNumeralString (this int value)
   {
      const int  MinValue = 1;
      const int  MaxValue = 3999;

      if ((value < MinValue) || (value > MaxValue))
      {
         throw new ArgumentOutOfRangeException (
            "value",
            value,
            "Argument out of Roman numeral range.");
      }

      const int  MaxRomanNumeralLength = 15;
      var        sb = new StringBuilder (MaxRomanNumeralLength);

      foreach (var  pair in m_romanNumerals)
      {
         while (value / pair.Value > 0)
         {
            sb.Append (pair.Key);
            value -= pair.Value;
         }
      }

      return sb.ToString ();
   }

   #endregion

   #region Private Static Member Data

   /// <summary>
   ///   The number of mappings in the dictionary.
   /// </summary>
   private const int                                NumberOfRomanNumeralMaps = 13;

   /// <summary>
   ///   The regular expression to test the string against.
   /// </summary>
   private static readonly Regex                    m_validRomanNumeral =
      new Regex (
         "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
         + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$",
         RegexOptions.Compiled);

   /// <summary>
   ///   The matching of Roman numeral placeholders to their integer
   ///   equivalents.
   /// </summary>
   private static readonly Dictionary<string, int>  m_romanNumerals =
      new Dictionary<string, int> (NumberOfRomanNumeralMaps)
   {
      { "M", 1000 },
      { "CM", 900 },
      { "D", 500 },
      { "CD", 400 },
      { "C", 100 },
      { "XC", 90 },
      { "L", 50 },
      { "XL", 40 },
      { "X", 10 },
      { "IX", 9 },
      { "V", 5 },
      { "IV", 4 },
      { "I", 1 }
   };

   #endregion
}

#endregion
}

Here's a to-and-from for Roman numerals. Not often used, but could be handy. Usage:

if ("IV".IsValidRomanNumeral())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral());
Console.WriteLine(3888.ToRomanNumeralString());
// <copyright file="RomanNumeralExtensions.cs" company="Always Elucidated Solution Pioneers, LLC">
// Copyright (c) 2008 Always Elucidated Solution Pioneers, LLC.  All Rights Reserved.
// </copyright>
// <author>Jesse C. Slicer</author>
// <email>[email protected]</email>
// <date>2008-10-01</date>
// <summary>Translates Roman numeral strings to integers and vice-versa.</summary>
    
namespace Aesop.Extensions
{
    // System namespaces
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// Holds the IsValidRomanNumeral(), ParseRomanNumeral() and ToRomanNumeralString() extension methods.
    /// </summary>
    public static class RomanNumeralExtensions
    {
        /// <summary>
        /// The number of mappings in the dictionary.
        /// </summary>
        private const int NumberOfRomanNumeralMaps = 13;

        /// <summary>
        /// The matching of Roman numeral placeholders to their integer equivalents.
        /// </summary>
        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        /// <summary>
        /// The regular expression to test the string against.
        /// </summary>
        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        /// <summary>
        /// Determines whether the specified string is a valid Roman numeral.
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string to validate.
        /// </param>
        /// <returns>
        /// <c>true</c> if the specified string is a valid Roman numeral; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        /// <summary>
        /// Parses the Roman numeral into its integer equivalent.
        /// </summary>
        /// <param name="value">
        /// The Roman numeral string.
        /// </param>
        /// <returns>
        /// The integer representation of the Roman numeral.
        /// </returns>
        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        /// <summary>
        /// Converts the number to its equivalent Roman numeral string.
        /// </summary>
        /// <param name="value">
        /// The integer to convert.
        /// </param>
        /// <returns>
        /// The Roman numeral representation of the integer.
        /// </returns>
        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }

    }
}
Source Link
Jesse C. Slicer
  • 20.2k
  • 5
  • 74
  • 91

Here's a to-and-from for Roman Numerals. Not often used, but could be handy. Usage:

if ("IV".IsValidRomanNumeral ())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine ("MMMDCCCLXXXVIII".ParseRomanNumeral ());
Console.WriteLine (3888.ToRomanNumeralString ());

The source:

// <copyright file="RomanNumeralExtensions.cs" company="Always Elucidated Solution Pioneers, LLC">
// Copyright (c) 2008 Always Elucidated Solution Pioneers, LLC.  All Rights Reserved.
// </copyright>
// <author>Jesse C. Slicer</author>
// <email>[email protected]</email>
// <date>2008-10-01</date>
// <summary>Translates Roman Numeral strings to integers and vice-versa.</summary>

namespace Aesop.Extensions
{
#region Using Directives

// System namespaces
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

#endregion

#region Static Class Definition : RomanNumeralExtensions

/// <summary>
///   Holds the IsValidRomanNumeral (), ParseRomanNumeral () and
///   ToRomanNumeralString () extension methods.
/// </summary>
public static class RomanNumeralExtensions
{
   #region Public Static Extension Methods

   /// <summary>
   ///   Determines whether the specified string is a valid Roman numeral.
   /// </summary>
   /// <param name="value">
   ///   The Roman numeral string to validate.
   /// </param>
   /// <returns>
   ///   <c>true</c> if the specified string is a valid Roman numeral;
   ///   otherwise, <c>false</c>.
   /// </returns>
   public static bool
   IsValidRomanNumeral (this string value)
   {
      return m_validRomanNumeral.IsMatch (value);
   }

   /// <summary>
   ///   Parses the Roman numeral into its integer equivalent.
   /// </summary>
   /// <param name="value">
   ///   The Roman numeral string.
   /// </param>
   /// <returns>
   ///   The integer representation of the Roman numeral.
   /// </returns>
   public static int
   ParseRomanNumeral (this string value)
   {
      if (value == null)
      {
         throw new ArgumentNullException ("value");
      }

      value = value.ToUpperInvariant ().Trim ();

      var  length = value.Length;
      
      if ((length == 0) || !value.IsValidRomanNumeral ())
      {
         throw new ArgumentException (
            "Empty or invalid Roman numeral string.",
            "value");
      }

      var  total = 0;
      var  i = length;
      
      while (i > 0)
      {
         var  digit = m_romanNumerals [value [--i].ToString ()];

         if (i > 0)
         {
            var  previousDigit = m_romanNumerals [value [i - 1].ToString ()];

            if (previousDigit < digit)
            {
               digit -= previousDigit;
               i--;
            }
         }

         total += digit;
      }

      return total;
   }

   /// <summary>
   ///   Converts the number to its equivalent Roman numeral string.
   /// </summary>
   /// <param name="value">
   ///   The integer to convert.
   /// </param>
   /// <returns>
   ///   The Roman numeral representation of the integer.
   /// </returns>
   public static string
   ToRomanNumeralString (this int value)
   {
      const int  MinValue = 1;
      const int  MaxValue = 3999;

      if ((value < MinValue) || (value > MaxValue))
      {
         throw new ArgumentOutOfRangeException (
            "value",
            value,
            "Argument out of Roman numeral range.");
      }

      const int  MaxRomanNumeralLength = 15;
      var        sb = new StringBuilder (MaxRomanNumeralLength);

      foreach (var  pair in m_romanNumerals)
      {
         while (value / pair.Value > 0)
         {
            sb.Append (pair.Key);
            value -= pair.Value;
         }
      }

      return sb.ToString ();
   }

   #endregion

   #region Private Static Member Data

   /// <summary>
   ///   The number of mappings in the dictionary.
   /// </summary>
   private const int                                NumberOfRomanNumeralMaps = 13;

   /// <summary>
   ///   The regular expression to test the string against.
   /// </summary>
   private static readonly Regex                    m_validRomanNumeral =
      new Regex (
         "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
         + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$",
         RegexOptions.Compiled);

   /// <summary>
   ///   The matching of Roman numeral placeholders to their integer
   ///   equivalents.
   /// </summary>
   private static readonly Dictionary<string, int>  m_romanNumerals =
      new Dictionary<string, int> (NumberOfRomanNumeralMaps)
   {
      { "M", 1000 },
      { "CM", 900 },
      { "D", 500 },
      { "CD", 400 },
      { "C", 100 },
      { "XC", 90 },
      { "L", 50 },
      { "XL", 40 },
      { "X", 10 },
      { "IX", 9 },
      { "V", 5 },
      { "IV", 4 },
      { "I", 1 }
   };

   #endregion
}

#endregion
}
Post Made Community Wiki by CommunityBot