using System; using System.Text; public class RadixConvert { /// /// インスタンス化を禁止しています。 /// private RadixConvert() { } #region Int16型およびUInt16型用のメソッド群 /// /// 3~36進数の数値文字列をInt16型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToInt16メソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static short ToInt16(string s, int radix) { ulong digit = ToUInt64(s, radix); CheckDigitOverflow(digit, Int16.MaxValue); return (short)digit; } /// /// 3~36進数の数値文字列をUInt16型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToUInt16メソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static ushort ToUInt16(string s, int radix) { ulong digit = ToUInt64(s, radix); CheckDigitOverflow(digit, UInt16.MaxValue); return (ushort)digit; } /// /// UInt16型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(short n, int radix, bool uppercase) { return ToString((ulong)n, radix, uppercase); } /// /// UInt16型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(ushort n, int radix, bool uppercase) { return ToString((ulong)n, radix, uppercase); } #endregion #region Int32型およびUInt32型用のメソッド群 /// /// 3~36進数の数値文字列をInt32型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToInt32メソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static int ToInt32(string s, int radix) { ulong digit = ToUInt64(s, radix); CheckDigitOverflow(digit, Int32.MaxValue); return (int)digit; } /// /// 3~36進数の数値文字列をUInt32型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToUInt32メソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static uint ToUInt32(string s, int radix) { ulong digit = ToUInt64(s, radix); CheckDigitOverflow(digit, UInt32.MaxValue); return (uint)digit; } /// /// UInt32型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(int n, int radix, bool uppercase) { return ToString((ulong)n, radix, uppercase); } /// /// UInt32型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(uint n, int radix, bool uppercase) { return ToString((ulong)n, radix, uppercase); } #endregion #region Int64型およびUInt64型用のメソッド群 /// /// 3~36進数の数値文字列をInt64型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToInt64メソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static long ToInt64(string s, int radix) { ulong digit = ToUInt64(s, radix); CheckDigitOverflow(digit, Int64.MaxValue); return (long)digit; } /// /// 3~36進数の数値文字列をUInt64型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToUInt64メソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static ulong ToUInt64(string s, int radix) { // 引数をチェックをする CheckNumberArgument(s); CheckRadixArgument(radix); ulong curValue = 0; // 変換中の数値 ulong maxValue = UInt64.MaxValue / (ulong)radix; // 最大値の1けた前の数値 // 数値文字列を解析して数値に変換する char num; // 処理中の1けたの数値文字列 int digit; // 処理中の1けたの数値 int length = s.Length; for (int i = 0; i < length; i++) { num = s[i]; digit = GetDigitFromNumber(num); CheckDigitOutOfRange(digit, radix); // 次にradixを掛けるときに数値がオーバーフローしないかを事前にチェックする CheckDigitOverflow(curValue, maxValue); curValue = curValue * (ulong)radix + (ulong)digit; } return curValue; } /// /// UInt64型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(long n, int radix, bool uppercase) { return ToString((ulong)n, radix, uppercase); } /// /// UInt64型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(ulong n, int radix, bool uppercase) { // 引数をチェックをする CheckRadixArgument(radix); // 数値の「0」は、どの進数でも「0」になる if (n == 0) { return "0"; } StringBuilder curValue = new StringBuilder(41); // 変換中の数値文字列 // ※UInt64.MaxValueの数値を3進数で表現すると41けたです。 ulong curDigit = n; // 未処理の数値 // 数値を解析して数値文字列に変換する ulong digit; // 処理中の1けたの数値 do { // 一番下のけたの数値を取り出す digit = curDigit % (ulong)radix; // 取り出した1けたを切り捨てる curDigit = curDigit / (ulong)radix; curValue.Insert(0, GetNumberFromDigit((int)digit, uppercase)); } while (curDigit != 0); return curValue.ToString(); } #endregion #region Decimal型用のメソッド群 /// /// 3~36進数の数値文字列をDecimal型の数値に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToDecimalメソッドを使ってください。 /// ※+や-の符号や0xなどのプレフィックスには対応していません。 /// ※引数となる数値文字列に、スペースなどの文字を含めないでください。 /// /// 数値文字列 /// 基数 /// 数値 public static decimal ToDecimal(string s, int radix) { // 引数をチェックをする CheckNumberArgument(s); CheckRadixArgument(radix); decimal curValue = 0; // 変換中の数値 decimal maxValue = Decimal.MaxValue / (decimal)radix; // 最大値の1けた前の数値 // 数値文字列を解析して数値に変換する char num; // 処理中の1けたの数値文字列 int digit; // 処理中の1けたの数値 int length = s.Length; for (int i = 0; i < length; i++) { num = s[i]; digit = GetDigitFromNumber(num); CheckDigitOutOfRange(digit, radix); // 次にradixを掛けるときに数値がオーバーフローしないかを事前にチェックする CheckDigitOverflow(curValue, maxValue); curValue = curValue * (decimal)radix + (decimal)digit; } return curValue; } /// /// Decimal型の数値を3~36進数の数値文字列に変換します。 /// /// /// ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 /// ※-符号には対応していません。 /// /// 数値 /// 基数 /// 大文字か(true)、小文字か(false) /// 数値文字列 public static string ToString(decimal n, int radix, bool uppercase) { // 引数をチェックをする CheckRadixArgument(radix); // 数値の「0」は、どの進数でも「0」になる if (n == 0) { return "0"; } StringBuilder curValue = new StringBuilder(120); // 変換中の数値文字列 // ※Decimal.MaxValueの数値を3進数で表現すると120けたです。 decimal curDigit = n; // 未処理の数値 // 数値を解析して数値文字列に変換する decimal digit; // 処理中の1けたの数値 do { // 一番下のけたの数値を取り出す digit = curDigit % (decimal)radix; // 取り出した1けたを切り捨てる curDigit = curDigit / (decimal)radix; curValue.Insert(0, GetNumberFromDigit((int)digit, uppercase)); } while (curDigit != 0); return curValue.ToString(); } #endregion #region 内部で使用しているメソッド群 private static void CheckNumberArgument(string s) { if (s == null || s == String.Empty) { throw new ArgumentException("数値文字列が指定されていません。"); } } private static void CheckRadixArgument(int radix) { if (radix == 2 || radix == 8 || radix == 10 || radix == 16) { throw new ArgumentException("2/8/10/16進数はSystem.Convertクラスを使ってください。"); } if (radix <= 1 || 36 < radix) { throw new ArgumentException("3~36進数にしか対応していません。"); } } private static void CheckDigitOutOfRange(int digit, int radix) { if (digit < 0 || radix <= digit) { throw new ArgumentOutOfRangeException("数値が範囲外です。"); } } private static void CheckDigitOverflow(ulong curValue, ulong maxValue) { if (curValue > maxValue) { throw new OverflowException("数値が最大値を超えました。"); } } private static void CheckDigitOverflow(decimal curValue, decimal maxValue) { if (curValue > maxValue) { throw new OverflowException("数値が最大値を超えました。"); } } private static int GetDigitFromNumber(char num) { if (num >= '0' && num <= '9') { return num - '0'; } else if (num >= 'A' && num <= 'Z') { return num - 'A' + 10; } else if (num >= 'a' && num <= 'z') { return num - 'a' + 10; } else { return -1; } } private static char GetNumberFromDigit(int digit, bool uppercase) { if (digit < 10) { return (char)('0' + digit); } else if (uppercase) { return (char)('A' + digit - 10); } else { return (char)('a' + digit - 10); } } #endregion }