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

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

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

Re[13]: ビット演算の方法に関して


(過去ログ 173 を表示中)

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

■99397 / inTopicNo.1)  ビット演算の方法に関して
  
□投稿者/ たろー (1回)-(2022/03/30(Wed) 10:32:50)

分類:[.NET 全般] 

2022/03/30(Wed) 10:55:01 編集(投稿者)
2022/03/30(Wed) 10:54:16 編集(投稿者)

VB.NETに関する質問です。

3バイトの配列があり、

そのうち、最初の12ビットだけ抽出して
2バイトのバイト配列にコピー

最後の12ビットだけを抽出して
別の2バイトのバイト配列にコピー
(バイト配列のindex0〜12bit目までにコピー)

というのを行いたいのですが
どのようにすれば良いですか?

いろいろと調べてみたのですが
方法が見つかりませんでした。



引用返信 編集キー/
■99400 / inTopicNo.2)  Re[1]: ビット演算の方法に関して
□投稿者/ kiku (248回)-(2022/03/30(Wed) 11:17:51)
No99397 (たろー さん) に返信
> 2022/03/30(Wed) 10:55:01 編集(投稿者)
> 2022/03/30(Wed) 10:54:16 編集(投稿者)
>
> VB.NETに関する質問です。
> 3バイトの配列があり、
> そのうち、最初の12ビットだけ抽出して
> 2バイトのバイト配列にコピー

C#ならサンプル書いたのですが、
VB.NETの指定なので、仕様の部分だけコメントします。

質問1
 下記案1から案4までのどれが望んでいる仕様でしょうか?

質問2
 下記ハイフンの部分は、0埋めですか?


入力
 1バイト目:12345678
 2バイト目:12345678
 3バイト目:12345678

最初の12bitを抽出した結果
案1
 1バイト目:12345678
 2バイト目:1234----
案2
 1バイト目:12345678
 2バイト目:5678----
案3
 1バイト目:12345678
 2バイト目:----1234
案4
 1バイト目:12345678
 2バイト目:----5678

引用返信 編集キー/
■99401 / inTopicNo.3)  Re[2]: ビット演算の方法に関して
□投稿者/ たろー (2回)-(2022/03/30(Wed) 11:25:30)
ありがとうございます。

案1
 1バイト目:12345678
 2バイト目:1234----

これで----は0埋めで大丈夫です。

引用返信 編集キー/
■99402 / inTopicNo.4)  Re[1]: ビット演算の方法に関して
□投稿者/ radian (25回)-(2022/03/30(Wed) 11:28:05)
2022/03/30(Wed) 11:37:35 編集(投稿者)

> いろいろと調べてみたのですが
> 方法が見つかりませんでした。

"vb.net ビット演算" で検索したらすぐ出てきませんかね。

[Visual Basic の論理演算子とビット処理演算子]
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/logical-and-bitwise-operators

[論理/ビット演算子 (Visual Basic)]
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/logical-bitwise-operators

1バイト目と3バイト目はそのままコピー出来るので、
あとは2バイト目を前後4ビットを取り出すビットマスクをそれぞれ作って、AND演算で取り出せばよいでしょう。

引用返信 編集キー/
■99403 / inTopicNo.5)  Re[3]: ビット演算の方法に関して
□投稿者/ kiku (249回)-(2022/03/30(Wed) 11:35:14)
No99401 (たろー さん) に返信
> ありがとうございます。
> 案1
>  1バイト目:12345678
>  2バイト目:1234----
> これで----は0埋めで大丈夫です。

後半は下記仕様でOKですか?

入力
 1バイト目:12345678
 2バイト目:12345678
 3バイト目:12345678

後半の12bitを抽出した結果
 2バイト目:----5678
 3バイト目:12345678
 ※ハイフンは0埋め

引用返信 編集キー/
■99404 / inTopicNo.6)  Re[4]: ビット演算の方法に関して
□投稿者/ たろー (3回)-(2022/03/30(Wed) 11:38:41)
いえ、以下の結果で取得したいと考えております。

後半の12bitを抽出した結果
 1バイト目:56781234
 2バイト目:5678----



引用返信 編集キー/
■99405 / inTopicNo.7)  Re[5]: ビット演算の方法に関して
□投稿者/ kiku (250回)-(2022/03/30(Wed) 11:45:07)
No99404 (たろー さん) に返信
> いえ、以下の結果で取得したいと考えております。
>
> 後半の12bitを抽出した結果
>  1バイト目:56781234
>  2バイト目:5678----

結果の1バイト目は、
入力の2バイト目の5678と、
入力の2バイト目の1234を入れ替えるという意味ですか?

結果の2バイト目は、
入力の3バイト目の5678を左に寄せるという意味ですか?
引用返信 編集キー/
■99406 / inTopicNo.8)  Re[6]: ビット演算の方法に関して
□投稿者/ kiku (251回)-(2022/03/30(Wed) 11:47:46)
No99405 (kiku さん) に返信
> ■No99404 (たろー さん) に返信
>>いえ、以下の結果で取得したいと考えております。
>>
>>後半の12bitを抽出した結果
>> 1バイト目:56781234
>> 2バイト目:5678----
>
> 結果の1バイト目は、
> 入力の2バイト目の5678と、
> 入力の2バイト目の1234を入れ替えるという意味ですか?
>
> 結果の2バイト目は、
> 入力の3バイト目の5678を左に寄せるという意味ですか?

あ、違いますね。

結果の1バイト目は、
入力の2バイト目の5678と、
入力の3バイト目の1234を結合ですね。

結果の2バイト目は、
入力の3バイト目の5678ですね。

引用返信 編集キー/
■99407 / inTopicNo.9)  Re[7]: ビット演算の方法に関して
□投稿者/ kiku (252回)-(2022/03/30(Wed) 11:54:58)
No99406 (kiku さん) に返信
> ■No99405 (kiku さん) に返信
>>■No99404 (たろー さん) に返信

仕様をまとめると下記ですね。
後はどなたかにお任せします。

入力
 1バイト目:12345678
 2バイト目:12345678
 3バイト目:12345678

前半12bitの結果
 1バイト目:入力1バイト目の前半(1234)+入力1バイト目の後半(5678)
 2バイト目:入力2バイト目の前半(1234)+0埋め(0000)

後半12bitの結果
 1バイト目:入力2バイト目の後半(5678)+入力3バイト目の前半(1234)
 2バイト目:入力3バイト目の後半(5678)+0埋め(0000)

引用返信 編集キー/
■99411 / inTopicNo.10)  Re[8]: ビット演算の方法に関して
□投稿者/ kiku (253回)-(2022/03/30(Wed) 16:43:49)
No99407 (kiku さん) に返信
> ■No99406 (kiku さん) に返信
>>■No99405 (kiku さん) に返信
> >>■No99404 (たろー さん) に返信
> 
> 仕様をまとめると下記ですね。
> 後はどなたかにお任せします。
> 
> 入力
>  1バイト目:12345678
>  2バイト目:12345678
>  3バイト目:12345678
> 
> 前半12bitの結果
>  1バイト目:入力1バイト目の前半(1234)+入力1バイト目の後半(5678)
>  2バイト目:入力2バイト目の前半(1234)+0埋め(0000)
> 
> 後半12bitの結果
>  1バイト目:入力2バイト目の後半(5678)+入力3バイト目の前半(1234)
>  2バイト目:入力3バイト目の後半(5678)+0埋め(0000)
> 

C#のソースですが、サンプル書いてみました。

            var input = new byte[] { 0x12, 0x34, 0x56 };

            var byte1前半 = (byte)((input[0] & 0xF0) >> 4);
            var byte1後半 = (byte)((input[0] & 0x0F) >> 0);
            var byte2前半 = (byte)((input[1] & 0xF0) >> 4);
            var byte2後半 = (byte)((input[1] & 0x0F) >> 0);
            var byte3前半 = (byte)((input[2] & 0xF0) >> 4);
            var byte3後半 = (byte)((input[2] & 0x0F) >> 0);

            var output前半 = new byte[] { (byte)((byte1前半 << 4) | (byte1後半 << 0)), (byte)(byte2前半 << 4) };
            var output後半 = new byte[] { (byte)((byte2後半 << 4) | (byte3前半 << 0)), (byte)(byte3後半 << 4) };

引用返信 編集キー/
■99413 / inTopicNo.11)  Re[9]: ビット演算の方法に関して
□投稿者/ furu (152回)-(2022/03/30(Wed) 18:51:50)
No99411 (kiku さん) に返信
> C#のソースですが、サンプル書いてみました。
3バイトなのでIntegerにしてしまったほうが楽かも。
普段使わないけどVB.NETで書いてみました。

Dim input() As Byte = New Byte() {&H12, &H34, &H56}

Dim x = input(0) * &H10000 + input(1) * &H100 + input(2)
Dim a = (x And &H_00FF0000) >> 16
Dim b = (x And &H_0000F000) >> 8
Dim c = (x And &H_00000FF0) >> 4
Dim d = (x And &H_0000000F) << 4

Dim output前半() As Byte = New Byte() {a, b}
Dim output後半() As Byte = New Byte() {c, d}
引用返信 編集キー/
■99417 / inTopicNo.12)  Re[10]: ビット演算の方法に関して
□投稿者/ kiku (254回)-(2022/03/31(Thu) 12:36:54)
No99413 (furu さん) に返信
> ■No99411 (kiku さん) に返信
>>C#のソースですが、サンプル書いてみました。
> 3バイトなのでIntegerにしてしまったほうが楽かも。
> 普段使わないけどVB.NETで書いてみました。

furuさん、ナイス。
引用返信 編集キー/
■99419 / inTopicNo.13)  Re[10]: ビット演算の方法に関して
□投稿者/ 魔界の仮面弁士 (3311回)-(2022/03/31(Thu) 14:45:42)
No99413 (furu さん) に返信
> ■No99411 (kiku さん) に返信
>> C#のソースですが、サンプル書いてみました。
> 普段使わないけどVB.NETで書いてみました。

3 バイトの配列を 12bit ごとに区切って、
2 個の 2 バイト配列に分解する関数を作ってみました。


Sub Main()
  Dim q = BitSplitter(&HAB, &HCD, &HEF)
  Console.WriteLine(BitConverter.ToString(q.Left))  'AB-C0
  Console.WriteLine(BitConverter.ToString(q.Right)) 'DE-F0
  Console.WriteLine()

  q = BitSplitter(&H12, &H34, &H56)
  Console.WriteLine(BitConverter.ToString(q.Left))  '12-30
  Console.WriteLine(BitConverter.ToString(q.Right)) '45-60
  Console.WriteLine()

  Dim bin3 As Byte() = {&H22, &H3, &H31}
  q = BitSplitter(bin3)
  Console.WriteLine(BitConverter.ToString(q.Left))  '22-00
  Console.WriteLine(BitConverter.ToString(q.Right)) '33-10
  Console.WriteLine()

  Console.ReadKey()
End Sub


Private Function BitSplitter(binary As Byte()) As (Left As Byte(), Right As Byte())
  Return BitSplitter(binary(0), binary(1), binary(2))
End Function

Private Function BitSplitter(a As Byte, b As Byte, c As Byte) As (Left As Byte(), Right As Byte())
  Return ({a, CByte(b And &HF0)}, {CByte((b << 4) Or (c >> 4)), c << 4})
End Function
引用返信 編集キー/
■99425 / inTopicNo.14)  Re[11]: ビット演算の方法に関して
□投稿者/ たろー (4回)-(2022/04/01(Fri) 16:20:23)
ありがとうございます。

furuさんの方法でうまくっていると思います。

魔界の仮面弁士さんの方法も試してみたのですが、

エラー BC30638 配列の範囲を、型指定子に記述することはできません。
エラー BC30198 ')' が必要です。
エラー BC30456 'Left' は '?()' のメンバーではありません。

というエラーが発生してしまいます。

何かコードの前で宣言が必要でしょうか?

引用返信 編集キー/
■99426 / inTopicNo.15)  Re[12]: ビット演算の方法に関して
□投稿者/ 魔界の仮面弁士 (3312回)-(2022/04/01(Fri) 19:58:50)
No99425 (たろー さん) に返信
> 魔界の仮面弁士さんの方法も試してみたのですが、

どのバージョンの Visual Basic をお使いですか?
また、ターゲット フレームワークの .NET バージョンは何でしょうか。

最新の Visual Studio 2022 であっても、.NET Framework 4.6.2 以下では動きません。
.NET Framework 4.7 / 4.7.1 / 4.7.2 / 4.8 であれば動くはずです。


もしも .NET 4 〜 4.6.2 をお使いの場合は、
 'ValueTuple 構造体を返す実装(要 .NET 4.7 以降)
 Private Function BitSplitter(a As Byte, b As Byte, c As Byte) As (Left As Byte(), Right As Byte())
  Return ({a, CByte(b And &HF0)}, {CByte((b << 4) Or (c >> 4)), c << 4})
 End Function
から、
 'Tuple クラスを返す実装(要 .NET 4 以降)
 Private Function BitSplitter(a As Byte, b As Byte, c As Byte) As Tuple(Of Byte(), Byte())
  Return Tuple.Create({a, CByte(b And &HF0)}, {CByte((b << 4) Or (c >> 4)), c << 4})
 End Function
に変更してみてください。

Tuple に変更した方の実装では、メンバー名が .Left / .Right から .Item1 / .Item2 に変化します。


VB.NET 2003、2005、2008 などのように、Tuple すら使えない環境の場合は、
 'ジャグ配列で返す実装
 Private Function BitSplitter(ByVal a As Byte, ByVal b As Byte, ByVal c As Byte) As Byte()()
  Return New Byte()() {New Byte() {a, CByte(b And &HF0)}, New Byte() {CByte((b << 4) Or (c >> 4)), c << 4}}
 End Function
などとして、
 Dim q As Byte()() = BitSplitter(&HAB, &HCD, &HEF)
 Dim l As Byte() = q(0) 'AB-C0
 Dim r As Byte() = q(1) 'DE-F0
のようにしてみてください。


さらに VB.NET 2002 まで遡る場合は、ビットシフト演算子を乗除算に置き換える必要があるでしょう。
引用返信 編集キー/
■99428 / inTopicNo.16)  Re[13]: ビット演算の方法に関して
□投稿者/ たろー (5回)-(2022/04/03(Sun) 19:48:28)
皆様、無事うまくいきました。
ありがとうございます。

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


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -