I am tyring to create a Roman Numeral Calculator in C#. I want this calculator to accept two numbers (in Roman Numeral form) and then allow a single mathematical operation to be performed (+, -, *, /).
Using Roman Numerals:
I=1, V=5, X=10, L=50, C=100, D=500, M=1000
I want this to prompt for the first operand (rom1), operator(+, -, *, /), second operand (rom2) and then display results.
I'd write a Roman Numeral class that (a) accepts a string in the constructor, (b) internally represents the number as an int, (c) has an add method, and (d) has a method to convert an int to roman numerals.
Code:
class RomanNumeral
{
public int number;
//Constructors
public RomanNumeral(int number) { this.number = number; }
public RomanNumeral(string numString) { this.number = parseString(numString); }
private static int parseString(string s) {
//Parse a roman-numeral string to an int
}
//Add two roman numerals
public static RomanNumeral add(RomanNumeral x, RomanNumeral y) {
return new RomanNumeral(x.number + y.number);
}
//Overload the + operator
public overload RomanNumeral operator+(RomanNumeral x, RomanNumeral y) {
return add(x,y);
}
public string getRomanNumeralString() {
//Return a string containing a roman-numeral representation of this.number
}
}
Best Regards,
BioPhysEngr http://blog.biophysengr.net
--
All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.
So, there apparently is a project euler problem about roman numerals and - since I find those fun anyway - I worked out the algorithms.
The algorithm for representing a number in Roman Numeral form is:
Create a list of all possible roman numeral "digits" (which includes I, V, X, L, C, D, M and the digraphs IV, IX, XL, XC, CD, CM with values 1, 5, 10, 50, 100, 500, 1000, and 4, 9, 40, 90, 400, 900, respectively). At each step, choose the "digit" with a value closest - without going over - to the remainder. Namely:
Code:
resultString = "";
while number > 0 do
resultString = resultString + highestDigitWithoutGoingOver;
number = number - valueOfLastDigitAdded;
loop
---
Similarly, to "read" a roman numeral string just scan from left to right. First check if any of the digraphs (IV, IX, ...) match at the current location. If so, add their value to your resulting int. Otherwise, check the single character digits (I, V, X...)
--
Hopefully that should be clear. If not here is my source code (in C#) to do parsing:
Code:
using System;
namespace PE89
{
class Program
{
static string[] glyphs = { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M" };
static int[] values = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
public static void Main(string[] args)
{
//Console.WriteLine(parseRN("MCMXCVI"));
//Console.WriteLine(toRN(parseRN("MCMXCVI")));
string[] lines = System.IO.File.ReadAllLines("roman.txt");
int savings = 0;
foreach(string line in lines)
{
string bestRep = toRN(parseRN(line));
savings += (line.Length - bestRep.Length);
}
Console.WriteLine(savings);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static int parseRN(string rn)
{
int result = 0;
int ptr = 0;
while( ptr < rn.Length )
{
int nextIndex = longestMatchingGlyphIndex(rn, ptr);
result += values[nextIndex];
ptr += glyphs[nextIndex].Length;
}
return result;
}
public static int longestMatchingGlyphIndex(string rn, int ptr)
{
int longest = -1;
int index = -1;
for(int i = 0; i < glyphs.Length; i++)
{
if( ptr + glyphs[i].Length > rn.Length )
continue;
if( glyphs[i].Length >= longest && rn.Substring(ptr, glyphs[i].Length) == glyphs[i] )
{
longest = glyphs[i].Length;
index = i;
}
}
return index;
}
public static string toRN(int number)
{
System.Text.StringBuilder result = new System.Text.StringBuilder();
while( number > 0 )
{
int index = highestGlyphWithoutExceeding(number);
result.Append(glyphs[index]);
number -= values[index];
}
return result.ToString();
}
public static int highestGlyphWithoutExceeding(int number)
{
for(int i = glyphs.Length - 1; i>= 0; i--)
{
if( values[i] <= number )
return i;
}
throw new ArgumentException();
}
}
}
Best Regards,
BioPhysEngr http://blog.biophysengr.net
--
All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.
You may find it easier to evaluate infix expressions if you first convert them to postfix (RPN). That link might help.
Good luck!
Best Regards,
BioPhysEngr http://blog.biophysengr.net
--
All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.
What about fractions, in other words the duodecimal system? The reaosn why I feel to mention this is because this system is a bit different than ours...
Bookmarks