|
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
IntroductionIn the whole arena of computer programming, there exists the problem to convert a number from one number system to another. I want to solve it in a more generic way to support more than one conversion scheme in future. In the following article, I want to explain four systems that were implemented into the
Using the codeTo use one concrete conversion, you simple use the Console.WriteLine(ConverterBase.Roman.ToString(1984));
The other direction works the same: Console.WriteLine(ConverterBase.Roman.ToInt("MCMLXXXIV"));
Static singleton propertyIf you look into the code, you'll see some things I love to do in the code. For example I define a static getter for accessing an instance of the concrete converter. It's a lazy creation, the instancing is done at the first access of the property! private static volatile ConverterBase binary;
static public ConverterBase Roman
{
get
{
if (roman == null)
roman = new RomanConverter();
return roman;
}
}
Hexadecimal, octal and binary systemsThese three conversions all use the class hexadecimal = new PositionalNotationConverter(16);
Roman number systemThis number system is a little more tricky but it is possible to implement a converter. Some use-cases for this converter are in numbering the contents in a document: I. II. III. and so on, or to show years in longer format like you see often in films. In the code, you'll see at first, the check for public override string ToString(int value)
{
if (value > MAX)
throw new ArgumentOutOfRangeException("value");
string[,] romanDigits = new string[,] {
{"M", "C", "X", "I" },
{"MM", "CC", "XX", "II" },
{"MMM", "CCC", "XXX", "III" },
{null, "CD", "XL", "IV" },
{null, "D", "L", "V" },
{null, "DC", "LX", "VI" },
{null, "DCC", "LXX", "VII" },
{null, "DCCC", "LXXX", "VIII" },
{null, "CM", "XC", "IX" }
};
StringBuilder result = new StringBuilder(15);
for (int index = 0; index < 4; index++)
{
int power = (int) Math.Pow(10, 3 - index);
int digit = value / power;
value -= digit * power;
if (digit > 0)
result.Append(romanDigits[digit - 1,index]);
}
return result.ToString();
}
For converting a Roman number back, the following code is used. Here the trick is to remember the old value. If it's greater than the current value it is reduced twice by the old value. Else it is only added. The public override int ToInt(string number)
{
int result = 0;
int oldValue = 1000;
for (int index = 0; index < number.Length; index++)
{
int newValue = RomanDigit(number[index]);
if (newValue > oldValue)
result = result + newValue - 2 * oldValue;
else
result += newValue;
oldValue = newValue;
}
return result;
}
Test-Case'sHere you see the test-cases I've written for the four conversion classes. That's how I check if my code works against one or more test scenarios. [TestFixture]
public class NumberConvertTest
{
[Test]
public void RomanNumber()
{
Assert.AreEqual("MCMLXXXIV", ConverterBase.Roman.ToString(1984));
Assert.AreEqual(1984, ConverterBase.Roman.ToInt("MCMLXXXIV"));
}
[Test]
public void HexNumber()
{
Assert.AreEqual("12FEAC", ConverterBase.Hexadecimal.ToString(0x12FeAC));
Assert.AreEqual(0x12FeAC, ConverterBase.Hexadecimal.ToInt("12FEAC"));
}
[Test]
public void OctNumber()
{
Assert.AreEqual("4553207", ConverterBase.Octal.ToString(1234567));
Assert.AreEqual(1234567, ConverterBase.Octal.ToInt("4553207"));
}
[Test]
public void BinaryNumber()
{
Assert.AreEqual("1010111111111110", ConverterBase.Binary.ToString(0xAFFE));
Assert.AreEqual(0xAFFE, ConverterBase.Binary.ToInt("1010111111111110"));
}
}
SummaryOkay, I hope that you like the code and can use it in your own projects. I want to hear from you your opinion about it. If you have your own conversion methods inherited from HistoryAbout xProcsxProcs is a free collection of methods that you can use in your own projects. If you have ideas or code to be included in this collection, send it to xProcs@hotmail.de.
|
||||||||||||||||||||||||||||||||||||||||||||