C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

整数==>2進文字列に変換

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■94505 / inTopicNo.1)  整数==>2進文字列に変換
  
□投稿者/ otu (7回)-(2020/04/16(Thu) 03:00:52)

分類:[VB.NET/VB2005 以降] 

環境:VB2017,.NET4.7.2

整数を2進文字列に変換したいのですが、判らない事があるので、ご指導下さい。
教えてもらいたいのは以下のコードに記載した★印の箇所です。

★(1):Int64型のMinValueをリテラルで宣言するとコンパイルエラーになります。
Long.MinValueやInt64.MinValueとすると大丈夫です。
リテラル表記ではエラーとなる仕様なのでしょうか?

★(2):SByte.MinValue(-128)をConvert.ToStringで2進文字列に変換すると
「1111111110000000」になり2バイトで返却されます。
自分の予想では最上位の符号ビットだけが立った1バイト「10000000」が返却される
と思っていたのですが違うのでしょうか?SByteって「-128〜127」の1バイトですよね?

★(3):UInt64型はConvert.ToStringでコンパイルエラーとなります。

以上、ご指導よろしくお願いします。

PS.その他の整数型も試したので変数名がv1からv15で途中欠番になっています。

    Private Sub ToolStripButton1_Click(sender As Object, e As EventArgs) Handles ToolStripButton1.Click
        Dim v1 As SByte = SByte.MinValue 
        Dim v15 As UInt64 = UInt64.MinValue
        Dim v16 As UInt64 = UInt64.MaxValue
        'Dim v17 As Int64 = -9223372036854775808L   ★(1)コンパイルエラー(オーバーフロー)
        Debug.WriteLine(Convert.ToString(v1, 2)) '1111111110000000 ★(2) 
        'Debug.WriteLine(Convert.ToString(v15, 2))  ★(3)コンパイルエラー(オーバーロードなし)
        'Debug.WriteLine(Convert.ToString(v16, 2))  ★(3)コンパイルエラー(オーバーロードなし)
    End Sub

引用返信 編集キー/
■94506 / inTopicNo.2)  Re[1]: 整数==>2進文字列に変換
□投稿者/ Azulean (1141回)-(2020/04/16(Thu) 06:06:38)
No94505 (otu さん) に返信
> ★(1):Int64型のMinValueをリテラルで宣言するとコンパイルエラーになります。
> Long.MinValueやInt64.MinValueとすると大丈夫です。
> リテラル表記ではエラーとなる仕様なのでしょうか?
詳しくないですが、仕様らしいです。
https://stackoverflow.com/questions/49113815/overflow-compiler-error-with-9223372036854775808l

符号のない、正の整数として解釈した後、-1 倍するみたいな解釈をするらしいです。
そのため、「9223372036854775808」がオーバーフローするのでコンパイルエラーとなるようです。
Int64.MinValue で十分じゃないでしょうか?


> ★(2):SByte.MinValue(-128)をConvert.ToStringで2進文字列に変換すると
> 「1111111110000000」になり2バイトで返却されます。
> 自分の予想では最上位の符号ビットだけが立った1バイト「10000000」が返却される
> と思っていたのですが違うのでしょうか?SByteって「-128〜127」の1バイトですよね?
Convert.ToString の一覧を確認してください。
https://docs.microsoft.com/ja-jp/dotnet/api/system.convert.tostring?view=netframework-4.8

SByte と Int32 をもらう引数は定義されていないので、Int16 と Int32 を渡すものを呼び出しているのでしょう。
本当に SByte で実現したいなら自分で書くか、コンパイルオプションのオーバーフローチェックを外してから CByte で Byte 型で処理するか…?
(後者はお勧めできませんが)

>
> ★(3):UInt64型はConvert.ToStringでコンパイルエラーとなります。
前述の URL を確認してみてください。
存在しないからです。必要なら自作するとか…。
引用返信 編集キー/
■94507 / inTopicNo.3)  Re[2]: 整数==>2進文字列に変換
□投稿者/ otu (8回)-(2020/04/16(Thu) 08:56:25)
No94506 (Azulean さん) に返信
ご指導、感謝致します。

>>★(1):Int64型のMinValueをリテラルで宣言するとコンパイルエラーになります。
>>Long.MinValueやInt64.MinValueとすると大丈夫です。
>>リテラル表記ではエラーとなる仕様なのでしょうか?
> 詳しくないですが、仕様らしいです。
> https://stackoverflow.com/questions/49113815/overflow-compiler-error-with-9223372036854775808l
>
> 符号のない、正の整数として解釈した後、-1 倍するみたいな解釈をするらしいです。
> そのため、「9223372036854775808」がオーバーフローするのでコンパイルエラーとなるようです。
> Int64.MinValue で十分じゃないでしょうか?

添付URLを読んで納得しました。そこに書かれてあるように16進や2進表記すればOKでした。
Dim v17 As Int64 = &H8000000000000000L
Dim v18 As Int64 = 1L << 63
Dim v19 As Int64 = &B10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L


>
>>★(2):SByte.MinValue(-128)をConvert.ToStringで2進文字列に変換すると
>>「1111111110000000」になり2バイトで返却されます。
>>自分の予想では最上位の符号ビットだけが立った1バイト「10000000」が返却される
>>と思っていたのですが違うのでしょうか?SByteって「-128〜127」の1バイトですよね?
> Convert.ToString の一覧を確認してください。
> https://docs.microsoft.com/ja-jp/dotnet/api/system.convert.tostring?view=netframework-4.8
>
> SByte と Int32 をもらう引数は定義されていないので、Int16 と Int32 を渡すものを呼び出しているのでしょう。
> 本当に SByte で実現したいなら自分で書くか、コンパイルオプションのオーバーフローチェックを外してから CByte で Byte 型で処理するか…?
> (後者はお勧めできませんが)
これもAzulean さんの説明で納得しました。
多分、暗黙でInt16にキャストされていると思っていましたが了解です。

>>
>>★(3):UInt64型はConvert.ToStringでコンパイルエラーとなります。
> 前述の URL を確認してみてください。
> 存在しないからです。必要なら自作するとか…。
了解です。ちゃんとリファレンスを見ていないのが原因ですね。
自作します。

どうも、ありがとうございました。
解決済み
引用返信 編集キー/
■94514 / inTopicNo.4)  Re[3]: 整数==>2進文字列に変換
□投稿者/ otu (9回)-(2020/04/16(Thu) 10:39:20)
No94507 (otu さん) に返信

BigIntegerの拡張メソッドとして、自作してみました。ついでだったので16進用も作っています。
他の人の役に立つかもしれないので、置いておきます。

これも、BigIntegerコンストラクタでSByteを取るオーバーロードはないですが、
暗黙でキャストされて問題ないみたいです。
一応、期待通りの結果が得られていると思いますが、問題点があればご指摘下さい。


Module BigIntegerExtensions
    'System.Numerics.dllへの参照を追加
    <Extension()>
    Public Function ToBinaryString(Of T)(ByVal bigint As BigInteger) As String
        'T型のByte数
        Dim byteT As Integer = Marshal.SizeOf(GetType(T))
        '0の場合はビット数分の0を返却
        If bigint.IsZero Then Return New String("0"c, byteT * 8)
        'BigInteger==>Byte配列
        Dim bytes = bigint.ToByteArray().ToList
        'Byte配列の要素数をT型のByte数に合わせる
        If bytes.Count <> byteT Then
            If bytes.Count > byteT Then
                '多い場合は末尾をカット
                bytes = bytes.Take(byteT).ToList
            Else
                '少ない場合は末尾に付け加える
                For i = 0 To byteT - bytes.Count - 1
                    bytes.Add(0)
                Next
            End If
        End If
        Dim ret = New StringBuilder(bytes.Count * 8)
        For i = bytes.Count - 1 To 0 Step -1
            Dim binary = Convert.ToString(bytes(i), 2).PadLeft(8, "0"c)
            ret.Append(binary)
        Next
        Return ret.ToString()
    End Function
    <Extension()>
    Public Function ToHexString(ByVal bigint As BigInteger) As String
        Return bigint.ToString("X")
    End Function
    <Extension()>
    Public Function ToHexString(ByVal bigint As BigInteger, digits As Integer) As String
        Return bigint.ToString("X").PadLeft(digits, "0"c)
    End Function
End Module

呼び出し側
Dim v1 As SByte = SByte.MinValue
Dim bigdec As BigInteger = New BigInteger(v1)
'2進
Debug.WriteLine(bigdec.ToBinaryString(Of SByte))
'16進
Debug.WriteLine(bigdec.ToHexString)
        '16進+桁数指定
Debug.WriteLine(bigdec.ToHexString(10))

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ