Zahlen in Strings verschiedener Basen umwandeln
Frank Dzaebel, Quelle: C#-NG, erstellt am: 20.1.2006, zuletzt geändert:  20.1.2006
Kategorie: Konvertierung, .NET-Version: 1.1/2.0

Es wird eine Klasse zur Umwandlung von Zahlen unterschiedlicher Basis in Strings und umgekehrt aufgezeigt.
Das .NET Framework 1.1/2.0 stellt mit seinen Convert-Methoden nur die Umwandlung der Basen 2, 8, 10 oder 16 zur Verfügung. Die folgenden Methoden beherrschen die (durchgängigen) Zahlen-Basen 1-36. Es ist weiterhin zu sehen, wie man eigene Exceptions implementieren kann.


using System;
using System.Windows.Forms;

namespace ConvertBase
{
  public partial class Form1 : Form
  { //  'partial' should be removed with .NET 1.1
    public Form1()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender,EventArgs e)
    {
      int    i1 = Convert.ToInt32("FF",16);         // = 255, only for base 2,4,8,16 possible
      string s1 = Convert.ToString(i1 ,16);         // = "ff"
      int    i2 = BaseConvert.ToInt32("-XyZ",36);   // = -44027 decimal
      string s2 = BaseConvert.ToString(i2   ,36);   // = "-XYZ"
      string s3 = BaseConvert.ToString("15E",16,20);// = "HA" 
    }
  }

  public class BaseConvert
  {
    /// <summary>The char '0' as int (48).</summary>
    const int Zero = (int)'0';
    /// <summary>The char '9' as int (57).</summary>
    const int Nine = (int)'9';
    /// <summary>The char 'A' as int (65).</summary>
    const int UpperA = (int)'A';
    /// <summary>The char 'Z' as int (90).</summary>
    const int UpperZ = (int)'Z';
    /// <summary>The char 'a' as int (65).</summary>
    const int LowerA = (int)'a';
    /// <summary>The char 'z' as int (90).</summary>
    const int LowerZ = (int)'z';
    /// <summary>This case 10</summary>
    const int TargetBase = 10;

    public static int ToInt32(string text,int fromBase)
    {
      int l = text.Length - 1;
      int s = 0;
      if (text[0] == '-') s++;
      int number = 0;
      for (int i = s; i <= l; i++)
      {
        int ch = (int)text[i];
        if ((ch >= Zero) && (ch <= Nine)) ch = ch - Zero;
        else if ((ch >= UpperA) && (ch <= UpperZ)) ch = ch - UpperA + TargetBase;
        else if ((ch >= LowerA) && (ch <= LowerZ)) ch = ch - LowerA + TargetBase;
        else ch = Int32.MaxValue;
        if (ch >= fromBase) throw new BaseConvertException(text[i],ch,i,fromBase);
        number = number * fromBase + ch;
      }
      if (s == 1) number = -number;
      return number;
    }

    public static string ToString(int number,int toBase)
    {
      char[] ach = new char[15];
      bool neg = false;
      if (number < 0)
      {
        neg = true;
        number = Math.Abs(number);
      }
      int i = ach.Length;
      int rmd;
      do
      {
        number = Math.DivRem(number,toBase,out rmd);
        if (rmd >= TargetBase)
          ach[--i] = (char)(rmd + UpperA - TargetBase);
        else
          ach[--i] = (char)(rmd + Zero);
      }
      while (number != 0);

      if (neg)
        ach[--i] = '-';

      return new String(ach,i,ach.Length - i);
    }

    public static string ToString(string number,int fromBase,int toBase)
    {
      int i = BaseConvert.ToInt32(number, fromBase);
      return BaseConvert.ToString(i,toBase);
    }
  }

  public class BaseConvertException : ArgumentException
  {
    private char chr;
    private int ch;
    private int pos;
    private int fromBase;

    public override string Message
    {
      get
      {
        // NOTE: text should be localized...
        return (String.Format("Invalid character: The " +
          "character '{0}'(int:{1}) at position {2} is higher than the " +
          "given base {3} or equal.",(char)chr,(int)ch,pos,fromBase));
      }
    }

    public BaseConvertException(char chr,int ch,int pos,int fromBase)
    {
      this.chr = chr;
      this.ch = ch;
      this.pos = pos;
      this.fromBase = fromBase;
    }
  }
}