Imports System Imports System.Text Public Class RadixConvert ''' ''' インスタンス化を禁止しています。 ''' Private Sub New() End Sub #Region "Int16型およびUInt16型用のメソッド群" ''' ''' 3~36進数の数値文字列をInt16型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToInt16メソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToInt16(ByVal s As String, ByVal radix As Integer) As Short Dim digit As ULong = ToUInt64(s, radix) CheckDigitOverflow(digit, Int16.MaxValue) Return CType(digit, Short) End Function ''' ''' 3~36進数の数値文字列をUInt16型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToUInt16メソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToUInt16(ByVal s As String, ByVal radix As Integer) As UShort Dim digit As ULong = ToUInt64(s, radix) CheckDigitOverflow(digit, UInt16.MaxValue) Return CType(digit, UShort) End Function ''' ''' UInt16型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As Short, ByVal radix As Integer, ByVal uppercase As Boolean) As String Return ToString(CType(n, ULong), radix, uppercase) End Function ''' ''' UInt16型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As UShort, ByVal radix As Integer, ByVal uppercase As Boolean) As String Return ToString(CType(n, ULong), radix, uppercase) End Function #End Region #Region "Int32型およびUInt32型用のメソッド群" ''' ''' 3~36進数の数値文字列をInt32型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToInt32メソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToInt32(ByVal s As String, ByVal radix As Integer) As Integer Dim digit As ULong = ToUInt64(s, radix) CheckDigitOverflow(digit, Int32.MaxValue) Return CType(digit, Integer) End Function ''' ''' 3~36進数の数値文字列をUInt32型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToUInt32メソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToUInt32(ByVal s As String, ByVal radix As Integer) As UInteger Dim digit As ULong = ToUInt64(s, radix) CheckDigitOverflow(digit, UInt32.MaxValue) Return CType(digit, UInteger) End Function ''' ''' UInt32型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As Integer, ByVal radix As Integer, ByVal uppercase As Boolean) As String Return ToString(CType(n, ULong), radix, uppercase) End Function ''' ''' UInt32型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As UInteger, ByVal radix As Integer, ByVal uppercase As Boolean) As String Return ToString(CType(n, ULong), radix, uppercase) End Function #End Region #Region "Int64型およびUInt64型用のメソッド群" ''' ''' 3~36進数の数値文字列をInt64型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToInt64メソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToInt64(ByVal s As String, ByVal radix As Integer) As Long Dim digit As ULong = ToUInt64(s, radix) CheckDigitOverflow(digit, Int64.MaxValue) Return CType(digit, Long) End Function ''' ''' 3~36進数の数値文字列をUInt64型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToUInt64メソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToUInt64(ByVal s As String, ByVal radix As Integer) As ULong ' 引数をチェックをする CheckNumberArgument(s) CheckRadixArgument(radix) Dim curValue As ULong = 0 ' 変換中の数値 Dim maxValue As ULong = UInt64.MaxValue / CType(radix, ULong) ' 最大値の1けた前の数値 ' 数値文字列を解析して数値に変換する Dim num As Char ' 処理中の1けたの数値文字列 Dim digit As Integer ' 処理中の1けたの数値 Dim length As Integer = s.Length For i As Integer = 0 To length - 1 num = s(i) digit = GetDigitFromNumber(num) CheckDigitOutOfRange(digit, radix) ' 次にradixを掛けるときに数値がオーバーフローしないかを事前にチェックする CheckDigitOverflow(curValue, maxValue) curValue = curValue * CType(radix, ULong) + CType(digit, ULong) Next Return curValue End Function ''' ''' UInt64型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As Long, ByVal radix As Integer, ByVal uppercase As Boolean) As String Return ToString(CType(n, ULong), radix, uppercase) End Function ''' ''' UInt64型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As ULong, ByVal radix As Integer, ByVal uppercase As Boolean) As String ' 引数をチェックをする CheckRadixArgument(radix) ' 数値の「0」は、どの進数でも「0」になる If n = 0 Then Return "0" End If Dim curValue As New StringBuilder(41) ' 変換中の数値文字列 ' ※UInt64.MaxValueの数値を3進数で表現すると41けたです。 Dim curDigit As ULong = n ' 未処理の数値 ' 数値を解析して数値文字列に変換する Dim digit As ULong ' 処理中の1けたの数値 Do ' 一番下のけたの数値を取り出す digit = curDigit Mod CType(radix, ULong) ' 取り出した1けたを切り捨てる curDigit = curDigit / CType(radix, ULong) curValue.Insert(0, GetNumberFromDigit(CType(digit, Integer), uppercase)) Loop While curDigit <> 0 Return curValue.ToString() End Function #End Region #Region "Decimal型用のメソッド群" ''' ''' 3~36進数の数値文字列をDecimal型の数値に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToDecimalメソッドを使ってください。 ''' ※+や-の符号や0xなどのプレフィックスには対応していません。 ''' ※引数となる数値文字列に、スペースなどの文字を含めないでください。 ''' ''' 数値文字列 ''' 基数 ''' 数値 Public Shared Function ToDecimal(ByVal s As String, ByVal radix As Integer) As Decimal ' 引数をチェックをする CheckNumberArgument(s) CheckRadixArgument(radix) Dim curValue As Decimal = 0 ' 変換中の数値 Dim maxValue As Decimal = Decimal.MaxValue / CType(radix, Decimal) ' 最大値の1けた前の数値 ' 数値文字列を解析して数値に変換する Dim num As Char ' 処理中の1けたの数値文字列 Dim digit As Integer ' 処理中の1けたの数値 Dim length As Integer = s.Length For i As Integer = 0 To length - 1 num = s(i) digit = GetDigitFromNumber(num) CheckDigitOutOfRange(digit, radix) ' 次にradixを掛けるときに数値がオーバーフローしないかを事前にチェックする CheckDigitOverflow(curValue, maxValue) curValue = curValue * CType(radix, Decimal) + CType(digit, Decimal) Next Return curValue End Function ''' ''' Decimal型の数値を3~36進数の数値文字列に変換します。 ''' ''' ''' ※2/8/10/16進数は、Convert.ToStringメソッドを使ってください。 ''' ※-符号には対応していません。 ''' ''' 数値 ''' 基数 ''' 大文字か(true)、小文字か(false) ''' 数値文字列 Public Overloads Shared Function ToString(ByVal n As Decimal, ByVal radix As Integer, ByVal uppercase As Boolean) As String ' 引数をチェックをする CheckRadixArgument(radix) ' 数値の「0」は、どの進数でも「0」になる If n = 0 Then Return "0" End If Dim curValue As New StringBuilder(120) ' 変換中の数値文字列 ' ※Decimal.MaxValueの数値を3進数で表現すると120けたです。 Dim curDigit As Decimal = n ' 未処理の数値 ' 数値を解析して数値文字列に変換する Dim digit As Decimal ' 処理中の1けたの数値 Do ' 一番下のけたの数値を取り出す digit = curDigit Mod CType(radix, Decimal) ' 取り出した1けたを切り捨てる curDigit = curDigit / CType(radix, Decimal) curValue.Insert(0, GetNumberFromDigit(CType(digit, Integer), uppercase)) Loop While curDigit <> 0 Return curValue.ToString() End Function #End Region #Region "内部で使用しているメソッド群" Private Shared Sub CheckNumberArgument(ByVal s As String) If s = Nothing OrElse s = String.Empty Then Throw New ArgumentException("数値文字列が指定されていません。") End If End Sub Private Shared Sub CheckRadixArgument(ByVal radix As Integer) If radix = 2 OrElse radix = 8 OrElse radix = 10 OrElse radix = 16 Then Throw New ArgumentException("2/8/10/16進数はSystem.Convertクラスを使ってください。") End If If radix <= 1 OrElse 36 < radix Then Throw New ArgumentException("3~36進数にしか対応していません。") End If End Sub Private Shared Sub CheckDigitOutOfRange(ByVal digit As Integer, ByVal radix As Integer) If digit < 0 OrElse radix <= digit Then Throw New ArgumentOutOfRangeException("数値が範囲外です。") End If End Sub Private Shared Sub CheckDigitOverflow(ByVal curValue As ULong, ByVal maxValue As ULong) If curValue > maxValue Then Throw New OverflowException("数値が最大値を超えました。") End If End Sub Private Shared Sub CheckDigitOverflow(ByVal curValue As Decimal, ByVal maxValue As Decimal) If curValue > maxValue Then Throw New OverflowException("数値が最大値を超えました。") End If End Sub Private Shared Function GetDigitFromNumber(ByVal num As Char) As Integer Dim ascNum As Integer = Asc(num) If ascNum >= Asc("0") AndAlso ascNum <= Asc("9") Then Return Asc(num) - Asc("0") ElseIf ascNum >= Asc("A") AndAlso ascNum <= Asc("Z") Then Return ascNum - Asc("A") + 10 ElseIf ascNum >= Asc("a") AndAlso ascNum <= Asc("z") Then Return Asc(ascNum) - Asc("a") + 10 Else Return -1 End If End Function Private Shared Function GetNumberFromDigit(ByVal digit As Integer, ByVal uppercase As Boolean) As Char If digit < 10 Then Return Chr(Asc("0") + digit) ElseIf uppercase Then Return Chr(Asc("A") + digit - 10) Else Return Chr(Asc("a") + digit - 10) End If End Function #End Region End Class