Konvertierung ganzer Zahlen in unterschiedliche Formate

1. Aufgabe

Wir betrachten diese Fallstudien in mehreren Teilabschnitten. Vorab beginnen wir mit einer Kurzbeschreibung der zum Einsatz kommenden Zahlenformate.

1.1 Binäre Darstellung

Das Binärsystem, auch Dualsystem oder Zweiersystem genannt, ist ein Zahlensystem, das nur zwei verschiedene Ziffern – in der Regel 0 und 1 – zur Darstellung von Zahlen benutzt. Die Ziffernfolge 1101 zum Beispiel, stellt nicht – wie im Dezimalsystem – die Tausendeinhundertundeins dar, sondern die Dreizehn, denn im Binärsystem berechnet sich der Wert durch

11012 = 1 * 23 + 1 * 22 + 0 * 21 + 1 * 20 = 1310

1.2 Hexadezimale Darstellung

Das Hexadezimalsystem, auch Sechzehnersystem genannt, ist ein Zahlensystem, das sechzehn verschiedene Ziffern zur Darstellung von Zahlen benutzt. Neben den Ziffern 0 bis 9 werden zusätzlich die Buchstaben A bis F (oder a bis f) als Zahlzeichen verwendet. Der hexadezimalen Ziffernfolge 9EA5 entspricht im Dezimalsystem der Wert

9EA516 = 9 * 163 + 15 * 162 + 10 * 161 + 5 * 160 = 9 * 4.096 + 14 * 256 + 10 * 16 + 5 = 36.864 + 3.584 + 160 + 5 = 40.61310

1.3 Duale BCD-Darstellung

Eine weiteres mögliches Format für ganze Zahlen ist die so genannte duale BCD-Darstellung. BCD ist die Abkürzung für „binary coded decimal“, bei dieser Darstellung wird jede Ziffer der Zahl einzeln in 4 Bits codiert, wie wir am Beispiel der Zahl 2365 zeigen:

0010 0011 0110 0101
  2    3    6    5

1.4 Schnittstelle IConvert

Bei einer Konvertierung müssen wir prinzipiell angeben, in welches Format (binär, dual BCD) wir konvertieren wollen. Ferner erhalten wir nach der Konvertierung ein Ergebnis. Da wir Variablen unterschiedlichen Typs – mit unterschiedlichen Algorithmen – konvertieren, teilen wir die beteiligten Eigenschaften und Methoden dieser Fallstudie deshalb auf mehrere Schnittstellen auf. Auf diese Weise können alle Zahlenkonvertierungen nach demselben Schema ablaufen.

Wir beginnen mit einer Schnittstelle IConvert, die zunächst nur die möglichen Konvertierungsmethoden und das Ergebnis festlegt. Definieren Sie eine Schnittstelle IConvert mit den folgenden Elementen (Tabelle 1):

Element

Beschreibung

Methode ConvertBinary

void ConvertBinary();

Berechnet die binäre Darstellung eines Werts. Das Ergebnis der Konvertierung wird in der Eigenschaft Result abgelegt, siehe weiter unten.

Methode ConvertDualBCD

void ConvertDualBCD();

Berechnet die duale BCD-Darstellung eines Werts. Das Ergebnis der Konvertierung wird in der Eigenschaft Result abgelegt, siehe weiter unten.

Eigenschaft Result

String Result { get; }

Beschreibt das Ergebnis einer Konvertierung. Beachten Sie dabei den Datentyp String dieser Eigenschaft. Er bietet sich an, da die numerischen Datentypen int bzw. long nicht für alle Zahlensysteme geeignet sind (siehe zum Beispiel die hexadezimale Darstellung).

Eigenschaft GroupSize

int GroupSize { get; set; }

Legt die Anzahl der Bits pro Gruppe fest – siehe Eigenschaft Result.

Tabelle 1. Elemente der Schnittstelle IConvert.


Mit der Eigenschaft GroupSize kann man die Anzahl der Bits pro Gruppe einstellen, um die Ergebniszeichenkette „ansehnlich“ zu gestalten. So sind die beiden Ergebniszeichenketten

01011011 11001101 00010101

bzw.

0110 1000 1011 0001

mit dem GroupSize-Wert 8 bzw. 4 gebildet worden.

1.5 Schnittstelle IConvertLong

Die Schnittstelle IConvertLong leitet sich von der Schnittstelle IConvert ab. Sie fügt zu den Elementen der IConvert-Schnittstelle eine Eigenschaft Number vom Typ long hinzu (Tabelle 2). Negative Zahlen spielen bei dieser Aufgabe keine Rolle, sie sollten außer Acht gelassen werden:

Element

Beschreibung

Eigenschaft Number

long Number { get; set; }

Spezifiziert die zu konvertierende Zahl vom Datentyp long.

Tabelle 2. Elemente der Schnittstelle IConvertLong.


Mit Hilfe der IConvertLong-Schnittstelle sind nun alle Details festgezurrt, die für eine binäre, hexadezimale oder duale BCD-Konvertierung notwendig sind.

1.6 Klasse LongConverter

Erstellen Sie eine Klasse LongConverter, die den Wert einer ganzen Zahl (Datentyp long) in seine binäre Darstellung konvertiert. Es versteht sich natürlich von selbst, dass die LongConverter-Klasse einen Vertrag mit der IConvertLong-Schnittstelle eingeht. Das folgende Code-Fragment demonstriert einen möglichen Anwendungsfall der LongConverter-Klasse:

LongConverter conv = new LongConverter();
conv.Number = 123456789;
Console.Write("{0}: ", conv.Number);
conv.GroupSize = 8;
conv.ConvertBinary();
Console.WriteLine(conv.Result);
conv.Number = 987654321;
Console.Write("{0}: ", conv.Number);
conv.GroupSize = 4;
conv.ConvertBinary();
Console.WriteLine(conv.Result);

Auf der Konsole produziert das Code-Fragment die Ausgabe

123456789: 00000111 01011011 11001101 00010101
987654321: 0011 1010 1101 1110 0110 1000 1011 0001

Hinweis: Es versteht sich von selbst, dass die Klasse Convert (Namensraum System) zum Zwecke des Übens in der Implementierung außen vor bleiben sollte.

1.7 Schnittstelle IConvertInteger

Die Schnittstelle IConvertInteger leitet sich von der Schnittstelle IConvert ab. Sie fügt zu den Elementen der IConvert-Schnittstelle eine Eigenschaft Number vom Typ int hinzu (Tabelle 3):

Element

Beschreibung

Eigenschaft Number

int Number { get; set; }

Spezifiziert die zu konvertierende Zahl vom Datentyp int.

Tabelle 3. Elemente der Schnittstelle IConvertInteger.

1.8 Klasse IntConverter

Erstellen Sie eine Klasse IntConverter, die den Wert einer ganzen Zahl in seine binäre Darstellung konvertiert. Natürlich geht die IntConverter-Klasse einen Vertrag mit der IConvertInteger-Schnittstelle ein. Im Prinzip arbeitet die IntConverter-Klasse wie die LongConverter-Klasse, sie kann allerdings nur Werte des Typs int konvertieren.

Das folgende Code-Fragment demonstriert eine Anwendung der Klasse IntConverter in der Praxis:

IntegerConverter conv = new IntegerConverter();
conv.Number = 65535;
Console.Write("{0}: ", conv.Number);
conv.GroupSize = 8;
conv.ConvertBinary();
Console.WriteLine(conv.Result);
conv.Number = 65536;
Console.Write("{0}: ", conv.Number);
conv.GroupSize = 8;
conv.ConvertBinary();
Console.WriteLine(conv.Result);
conv.Number = 255;
Console.Write("{0}: ", conv.Number);
conv.GroupSize = 4;
conv.ConvertBinary();
Console.WriteLine(conv.Result);
conv.Number = 256;
Console.Write("{0}: ", conv.Number);
conv.GroupSize = 4;
conv.ConvertBinary();
Console.WriteLine(conv.Result);

Auf der Konsole produziert das Code-Fragment die Ausgabe

65535: 11111111 11111111
65536: 00000001 00000000 00000000
255: 1111 1111
256: 0001 0000 0000

Hinweis: Eine clevere Implementierung der Klasse IntConverter nimmt Hilfeleistungen der Klasse LongConverter in Anspruch. Sie müssen also nicht zwingend alle Methoden der Klasse IntConverter von Neuem implementieren.

1.9 Klasse BigNumber

Wir verallgemeinern unsere bisherigen Überlegungen und betrachten nun die binäre Darstellung von natürlichen Zahlen, die potentiell unendlich groß sein können. Die elementaren Datentypen int bzw. long scheiden damit für die Ablage des zu konvertierenden Zahlenwerts aus, da ihr Wertebereich begrenzt ist.

Zur Verarbeitung beliebig großer Zahl führen wir nun die Klasse BigNumber ein (Tabelle 4). Wenn wir die beliebig große Zahl mit Hilfe einer Zeichenkette darstellen, also etwa "11111111111111111111111111111111111", und einen Konstruktor der BigNumber-Klasse dementsprechend zur Verfügung stellen, lassen sich beliebig große Zahlen in BigNumber-Objekten darstellen.

Element

Beschreibung

Konstruktor

public BigNumber();

Der Standard-Konstruktor belegt das Objekt mit dem Wert 0 vor.

Konstruktor

public BigNumber(String s);

Mit dem benutzerdefinierter Konstruktor wird ein Objekt initialisiert, dessen Wert durch die Zeichenkette s beschrieben wird:

BigNumber big = new BigNumber("12345678987654321");

Eigenschaft IsNull

public bool IsNull { get; }

Mit dieser Eigenschaft kann man abfragen, ob die Zahl 0 vorliegt.

Eigenschaft Length

public int Length { get; }

Liefert die Anzahl der Ziffern des BigNumber-Objekts zurück.

Methode DivideByTwo

public BigNumber DivideByTwo();

Führt am vorliegenden BigNumber-Objekt eine Division durch 2 aus. Das Ergebnis wird in einem neuen BigNumber-Objekt abgelegt:

BigNumber big = new BigNumber("12345");
BigNumber half = big.DivideByTwo();

Zur Implementierung der Methode legen Sie Ihre Erinnerungen an die Schulmathematik zu Grunde:

12345 : 2 = 6172
12
-----
 03
  2
-----
  14
  14
-----
   05
    4
-----
    1

Methode RemainderModulusTwo

public int RemainderModulusTwo();

Berechnet am vorliegenden BigNumber-Objekt den Rest bei der Division durch 2.

Tabelle 4. Elemente der Klasse BigNumber.


Hinweis: Zur Ablage der Ziffern eines BigNumber-Objekts bietet sich eine Variable des Typs List<int> an. Eine Implementierung der beiden Methoden DivideByTwo und RemainderModulusTwo ist auf Basis dieser Datenstruktur nicht übermäßig kompliziert!

Bitte beachten Sie: Weitere Methoden oder Operatoren, um BigNumber-Objekte addieren, subtrahieren etc. zu können, sind nicht erforderlich. Wir führen diese Klasse nur zum Zwecke des Konvertierens ganzer Zahlen in andere Zahlenformate ein.

1.10 Schnittstelle IConvertBigNumber

Leiten Sie die Schnittstelle IConvertBigNumber von der Schnittstelle IConvert ab. Fügen Sie eine Eigenschaft Number des Typs BigNumber hinzu (Tabelle 5):

Element

Beschreibung

Eigenschaft Number

BigNumber Number { get; set; }

Spezifiziert die zu konvertierende Zahl vom Datentyp BigNumber.

Tabelle 5. Elemente der Schnittstelle IConvertBigNumber.

1.11 Klasse BigNumberConverter

Erstellen Sie eine Klasse BigNumberConverter, die den Wert eines BigNumber-Objekts in seine binäre Darstellung konvertiert. Welchen Vertrag wird die BigNumberConverter-Klasse wohl eingehen? Das folgende Code-Fragment demonstriert einen möglichen Anwendungsfall der BigNumberConverter-Klasse:

BigNumberConverter conv = new BigNumberConverter();
conv.Number = new BigNumber("256");
Console.Write("{0}: ", conv.Number);
conv.ConvertBinary();
Console.WriteLine(conv.Result);
conv.Number = new BigNumber("4096");
Console.Write("{0}: ", conv.Number);
conv.ConvertBinary();
Console.WriteLine(conv.Result);
conv.Number = new BigNumber("2475880078570760549798248448");
Console.Write("{0}: ", conv.Number);
conv.ConvertBinary();
Console.WriteLine(conv.Result);

Ausgabe:

256: 1 0000 0000
4096: 1 0000 0000 0000
2475880078570760549798248448:
1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

Hinweis: Zum Zwecke der besseren Lesbarkeit wurde die Ausgabe geringfügig an die Fensterbreite angepasst.

Bitte beachten Sie: Die Realisierung der Methode ConvertBinary ist auf Basis der BigNumberConverter-Schnittstelle einfach zu stemmen. Für die binäre Darstellung eines Zahlenwerts genügt es, zwei Methoden für die Division durch 2 bzw. den Rest bei Division durch 2 zur Hand zu haben.

Ergänzen Sie die Klasse BigNumberConverter um eine Implementierung der ConvertDualBCD-Methode zur Berechnung der dualen BCD-Darstellung eines BigNumber-Objekts:

BigNumberConverter conv = new BigNumberConverter();
conv.Number = new BigNumber("123456789");
Console.Write("{0}: ", conv.Number);
conv.ConvertDualBCD();
Console.WriteLine(conv.Result);

Ausgabe:

123456789: 0001 0010 0011 0100 0101 0110 0111 1000 1001

Und zum Abschluss noch ein Beispiel für die binäre und hexadezimale Konvertierung:

BigNumberConverter conv = new BigNumberConverter();
conv.Number = new BigNumber("1111111111111111111"); ;
conv.ConvertHexadecimal();
Console.WriteLine(conv.Result);
conv.ConvertBinary();
Console.WriteLine(conv.Result);

Ausgabe:

F6B 75AB 2BC4 71C7
1111 0110 1011 0111 0101 1010 1011 0010 1011 1100 0100 0111 0001 1100 0111

Mit dem Windows Taschenrechner kann man sich von der Korrektheit des Ergebnisses überzeugen (Abbildung 1):

Die Zahl 1.111.111.111.111.111.111 in unterschiedlichen Formaten.

Abbildung 1. Die Zahl 1.111.111.111.111.111.111 in unterschiedlichen Formaten.

2. Lösung

Quellcode: Siehe auch github.com/peterloos/CSharp_NumericConversions.git.

Für die ersten Teile der Lösung bedarf es keiner zusätzlichen Erläuterungen (Listing 1, Listing 2 und Listing 3):

01: public interface IConvert
02: {
03:     String Result { get; }
04:     int GroupSize { get; set; }
05: 
06:     void ConvertBinary();
07:     void ConvertDualBCD();
08:     void ConvertHexadecimal();
09: }

Beispiel 1. Definition der Schnittstelle IConvert.


01: public interface IConvertLong : IConvert
02: {
03:     long Number { get; set; }
04: }

Beispiel 2. Definition der Schnittstelle IConvertLong.


001: public class LongConverter : IConvertLong
002: {
003:     private long number;     // number to convert
004:     private String result;   // result of conversion
005:     private int groupSize;   // number of bits in a group
006: 
007:     // c'tor
008:     public LongConverter()
009:     {
010:         this.number = 0;
011:         this.result = "";
012:         this.groupSize = 4;
013:     }
014: 
015:     // properties
016:     public String Result
017:     {
018:         get { return this.result; }
019:     }
020: 
021:     public long Number
022:     {
023:         get { return this.number; }
024:         set { this.number = value; }
025:     }
026: 
027:     public int GroupSize
028:     {
029:         get { return this.groupSize; }
030:         set { this.groupSize = value; }
031:     }
032: 
033:     // methods
034:     public void ConvertBinary()
035:     {
036:         StringBuilder sb = new StringBuilder();
037: 
038:         long n = this.number;
039: 
040:         if (n == 0)
041:         {
042:             if (this.groupSize == 4)
043:                 sb.Append("0000");
044:             else if (this.groupSize == 8)
045:                 sb.Append("00000000");
046:             else 
047:                 sb.Append("0000");
048:         }
049:         else
050:         {
051:             int separator = 0;
052:             while (n != 0)
053:             {
054:                 long remainder = n % 2;
055:                 n /= 2;
056: 
057:                 sb.Insert(0, (remainder == 1) ? "1" : "0");
058: 
059:                 separator++;
060:                 if (separator % this.groupSize == 0 && n != 0)
061:                     sb.Insert(0, " ");
062:             }
063: 
064:             // add leading zero's
065:             while (separator % this.groupSize != 0)
066:             {
067:                 sb.Insert(0, "0");
068:                 separator++;
069:             }
070:         }
071: 
072:         this.result = sb.ToString();
073:     }
074: 
075:     public void ConvertHexadecimal()
076:     {
077:         StringBuilder sb = new StringBuilder();
078: 
079:         long n = this.number;
080: 
081:         if (n == 0)
082:         {
083:             if (this.groupSize == 4)
084:                 sb.Append("0000");
085:             else if (this.groupSize == 8)
086:                 sb.Append("00000000");
087:             else
088:                 sb.Append("0000");
089:         }
090:         else
091:         {
092:             int separator = 0;
093:             while (n != 0)
094:             {
095:                 long rest = n % 16;
096:                 n /= 16;
097: 
098:                 if (rest >= 0 && rest < 9)
099:                 {
100:                     sb.Insert(0, (char) ('0' + rest));
101:                 }
102:                 else
103:                 {
104:                     sb.Insert(0, (char)('A' + (rest - 10)));
105:                 }
106: 
107:                 separator++;
108:                 if (separator % this.groupSize == 0 && n != 0)
109:                     sb.Insert(0, " ");
110:             }
111: 
112:             // add leading zero's
113:             while (separator % this.groupSize != 0)
114:             {
115:                 sb.Insert(0, "0");
116:                 separator++;
117:             }
118:         }
119: 
120:         this.result = sb.ToString();
121:     }
122: 
123:     public void ConvertDualBCD()
124:     {
125:         StringBuilder sb = new StringBuilder();
126: 
127:         LongConverter conv = new LongConverter();
128: 
129:         for (long n = number; n != 0; n /= 10)
130:         {
131:             conv.Number = n % 10;
132:             conv.ConvertBinary();
133:             String s = conv.Result;
134: 
135:             // add leading zero's, if necessary
136:             if (s.Length == 1)
137:                 s = "000" + s;
138:             else if (s.Length == 2)
139:                 s = "00" + s;
140:             else if (s.Length == 3)
141:                 s = "0" + s;
142: 
143:             if (n != number)
144:                 sb.Insert(0, " ");
145:             sb.Insert(0, s);
146:         }
147: 
148:         this.result = sb.ToString();
149:     }
150: 
151:     // overrides
152:     public override String ToString()
153:     {
154:         return String.Format("{0} ==> {1}", this.number, this.result);
155:     }
156: }

Beispiel 3. Definition der Klasse LongConverter.


Bei der Realisierung eines Konverters für int-Zahlen steht man zunächst vor der Fragestellung: „Warum einen zweiten Konverter schreiben, wenn es bereits einen für long-Zahlen gibt?“ Gegen eine datentyp-konforme Klasse zum Konvertieren ist sicherlich nichts einzuwenden – in der Realisierung bietet es sich aber an, eine Instanz der LongConverter-Klasse mit einzubeziehen. Achten Sie in Listing 5 auf die entsprechenden Stellen (zum Beispiel die Zeilen 5, 13, 38 bis 40 etc.). Vorab fahren wir in Listing 4 mit der Schnittstelle IConvertInteger fort:

01: public interface IConvertInteger : IConvert
02: {
03:     int Number { get; set; }
04: }

Beispiel 4. Definition der Schnittstelle IConvertInteger.


01: public class IntegerConverter : IConvertInteger
02: {
03:     private int number;           // number to convert
04:     private String result;        // result of conversion
05:     private LongConverter conv;   // reusing LongConverter
06: 
07:     // c'tor
08:     public IntegerConverter()
09:     {
10:         this.number = 0;
11:         this.result = "";
12: 
13:         this.conv = new LongConverter();
14:         this.conv.GroupSize = 4;
15:     }
16: 
17:     // properties
18:     public String Result
19:     {
20:         get { return this.result; }
21:     }
22: 
23:     public int Number
24:     {
25:         get { return this.number; }
26:         set { this.number = value; }
27:     }
28: 
29:     public int GroupSize
30:     {
31:         get { return this.conv.GroupSize; }
32:         set { this.conv.GroupSize = value; }
33:     }
34: 
35:     // methods
36:     public void ConvertBinary()
37:     {
38:         this.conv.Number = this.Number;
39:         this.conv.ConvertBinary();
40:         this.result = this.conv.Result;
41:     }
42: 
43:     public void ConvertDualBCD()
44:     {
45:         this.conv.Number = this.Number;
46:         this.conv.ConvertDualBCD();
47:         this.result = this.conv.Result;
48:     }
49: 
50:     public void ConvertHexadecimal()
51:     {
52:         this.conv.Number = this.Number;
53:         this.conv.ConvertHexadecimal();
54:         this.result = this.conv.Result;
55:     }
56: 
57:     // overrides
58:     public override String ToString()
59:     {
60:         return String.Format("{0} ==> {1}", this.number, this.result);
61:     }
62: }

Beispiel 5. Definition der Schnittstelle IntegerConverter.


int- und long-Zahlen sind bezüglich ihres Wertebereichs begrenzt. Wollen wir numerische Konvertierungen für beliebig große Zahlen betrachten, lässt sich dies mit vergleichsweise wenigen Arbeitsschritten bewerkstelligen. Zunächst entwickeln wir eine Klasse BigNumber, die beliebig große Zahlen darstellen kann. Um die drei numerischen Konvertierungen binär, hexadezimal und dual BCD implementieren zu können, kommt man unter Zugrundelegung eines minimalen Realisierungsaufwands mit den beiden Methoden „Division durch Zwei“ und „Rest bei Division durch Zwei“ ans Ziel (Listing 6):

001: public class BigNumber : ICloneable
002: {
003:     private List<int> numbers;
004: 
005:     // c'tors
006:     public BigNumber() : this("0") { }
007: 
008:     public BigNumber(String s)
009:     {
010:         this.numbers = new List<int>();
011:         for (int i = 0; i < s.Length; i++)
012:             this.numbers.Add(s[i] - '0');
013: 
014:         this.RemoveLeadingZeroes();
015:     }
016: 
017:     private BigNumber(List<int> numbers)
018:     {
019:         this.numbers = new List<int>(numbers);
020:     }
021: 
022:     // properties
023:     public bool IsNull
024:     {
025:         get
026:         {
027:             for (int i = 0; i < this.numbers.Count; i++)
028:             {
029:                 if (this.numbers[i] != 0)
030:                     return false;
031:             }
032: 
033:             return true;
034:         }
035:     }
036: 
037:     public int Length
038:     {
039:         get
040:         {
041:             return this.numbers.Count;
042:         }
043:     }
044: 
045:     // indexer
046:     public int this [int i]
047:     {
048:         get
049:         {
050:             return this.numbers[i];
051:         }
052:     }
053: 
054:     // methods
055:     public BigNumber DivideByTwo()
056:     {
057:         StringBuilder result = new StringBuilder();
058: 
059:         int rest = 0;
060:         for (int i = 0; i < this.numbers.Count; i++)
061:         {
062:             int current = (this.numbers[i] + 10 * rest) / 2;
063:             result.Append(current);
064:             rest = (this.numbers[i] + 10 * rest) % 2;
065:         }
066: 
067:         return new BigNumber(result.ToString());
068:     }
069: 
070:     public int RemainderModulusTwo()
071:     {
072:         return (this.numbers[this.numbers.Count - 1] % 2);
073:     }
074: 
075:     private void RemoveLeadingZeroes()
076:     {
077:         if (this.numbers.Count != 0)
078:         {
079:             while (this.numbers[0] == 0)
080:             {
081:                 this.numbers.RemoveAt(0);
082: 
083:                 if (this.numbers.Count == 0)
084:                 {
085:                     this.numbers.Add(0);
086:                     break;
087:                 }
088:             }
089:         }
090:     }
091: 
092:     // overrides
093:     public override String ToString()
094:     {
095:         StringBuilder sb = new StringBuilder();
096: 
097:         for (int i = 0; i < this.numbers.Count; i++)
098:             sb.Append(this.numbers[i]);
099: 
100:         return sb.ToString();
101:     }
102: 
103:     // implementation of interface 'ICloneable'
104:     public Object Clone()
105:     {
106:         return new BigNumber(this.numbers);
107:     }
108: }

Beispiel 6. Definition der Schnittstelle BigNumber.


Damit sind wir auch schon fast am Ende angekommen. Die noch ausstehende Schnittstelle IConvertBigNumber sowie die Implementierung des Konverters für BigNumber-Objekte entnehmen Sie bitte Listing 7 und Listing 8:

01: public interface IConvertBigNumber : IConvert
02: {
03:     BigNumber Number { get; set; }
04: }

Beispiel 7. Definition der Schnittstelle IConvertBigNumber.


001: class BigNumberConverter : IConvertBigNumber
002: {
003:     private BigNumber number; // number to convert
004:     private String result;    // result of conversion
005:     private int groupSize;    // number of bits in a group 
006: 
007:     // c'tor
008:     public BigNumberConverter()
009:     {
010:         this.result = "";
011:         this.groupSize = 4;
012:     }
013: 
014:     // properties
015:     public String Result
016:     {
017:         get { return this.result; }
018:     }
019: 
020:     public BigNumber Number
021:     {
022:         get { return this.number; }
023:         set { this.number = value; }
024:     }
025: 
026:     public int GroupSize
027:     {
028:         get { return this.groupSize; }
029:         set { this.groupSize = value; }
030:     }
031: 
032:     // methods
033:     public void ConvertBinary()
034:     {
035:         StringBuilder sb = new StringBuilder("");
036: 
037:         int separator = 0;
038: 
039:         while (!number.IsNull)
040:         {
041:             sb.Insert(0, (number.RemainderModulusTwo() == 1) ? "1" : "0");
042:             number = number.DivideByTwo();
043: 
044:             separator++;
045:             if (separator % this.groupSize == 0 && !number.IsNull)
046:                 sb.Insert(0, " ");
047:         }
048: 
049:         this.result = sb.ToString();
050:     }
051: 
052:     public void ConvertDualBCD()
053:     {
054:         StringBuilder sb = new StringBuilder();
055:         IntegerConverter conv = new IntegerConverter();
056: 
057:         for (int i = 0; i < this.Number.Length; i++)
058:         {
059:             conv.Number = this.Number[i];
060:             conv.ConvertDualBCD();
061: 
062:             if (i > 0)
063:                 sb.Append (" ");
064: 
065:             sb.Append (conv.Result);
066:         }
067: 
068:         this.result = sb.ToString();
069:     }
070: 
071:     public void ConvertHexadecimal()
072:     {
073:         StringBuilder sb = new StringBuilder("");
074: 
075:         int separator = 0;
076: 
077:         BigNumber num = (BigNumber) this.number.Clone();
078: 
079:         while (!num.IsNull)
080:         {
081:             int rem1 = num.RemainderModulusTwo();
082:             num = num.DivideByTwo();
083:             int rem2 = num.RemainderModulusTwo();
084:             num = num.DivideByTwo();
085:             int rem3 = num.RemainderModulusTwo();
086:             num = num.DivideByTwo();
087:             int rem4 = num.RemainderModulusTwo();
088:             num = num.DivideByTwo();
089: 
090:             int remainder = rem1 + 2 * (rem2 + 2 * (rem3 + 2 * rem4));
091: 
092:             if (remainder >= 0 && remainder < 10)
093:             {
094:                 sb.Insert(0, (char)('0' + remainder));
095:             }
096:             else
097:             {
098:                 sb.Insert(0, (char)('A' + (remainder - 10)));
099:             }
100: 
101:             separator++;
102:             if (separator % this.groupSize == 0 && !num.IsNull)
103:                 sb.Insert(0, " ");
104:         }
105: 
106:         this.result = sb.ToString();
107:     }
108: }

Beispiel 8. Definition der Schnittstelle BigNumberConverter.