• ベストアンサー

このような計算はできるでしょうか?

現在 「2バイトの数値」から「ビットが1である数」を求める 計算を行おうと思っています。 例えば、2バイトの数値が「222」の場合 →ビットに直すと「11011110」となり →ビットが1である数は「6」となります。 この計算をVBで行いたいのですが、 効率的に行える方法はないでしょうか? AND演算を行い1ビットずつカウントすると いう方法を考えたのすが、判定の時IF文がはいってしまうため 処理速度が遅くなり、困っております。 どなたか、お気づきの方はご教授ください。

質問者が選んだベストアンサー

  • ベストアンサー
  • maruru01
  • ベストアンサー率51% (1179/2272)
回答No.1

こんにちは。maruru01です。 ちょっと強引な方法ですが。 処理速度は確かめていません。 Dim temp As Long Dim tempOct As String Dim i As Long Dim cnt As Long temp = 222 tempOct = Oct(temp) cnt = 0 For i = 1 To Len(tempOct)   cnt = cnt + CLng(Mid("01121223", Mid(tempOct, i, 1) + 1, 1)) Next i MsgBox cnt

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (6)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.7

教科書に書いてある10進->2進変換の通常方法の、2で割る方法はダメですか。エクセルVBAでテストしました。カウントする変数にn Mod 2が1であれば1を足せば良いのでは。これだと判ってるわいといわれそうですが。 技術計算や数値解析の繰り返し計算の膨大なルーチンですか。「判定の時IF文がはいってしまうため処理速度が遅くなり」-今時のコンピューターで信じられない。 Sub test01() n = Cells(1, 1) s = "" '2進数文字列を表示するため b = 0 '1のビットの数 For i = 1 To 16 If (n Mod 2) = 1 Then b = b + 1 s = (n Mod 2) & s n = Int(n / 2) If n < 2 Then GoTo p01 Next i p01: If (n Mod 2) = 1 Then b = b + 1 s = (n Mod 2) & s MsgBox s MsgBox b End Sub

takatoo
質問者

お礼

お礼が遅れて申し訳ございません。 皆様にまとめてお礼を申し上げさせていただきます。 たくさんの方から回答いただき感激です。 大変参考になりました。 ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • todo36
  • ベストアンサー率58% (728/1234)
回答No.6

あ、2byte整数ね。 Private Declare Sub MoveMemory Lib "kernel32.dll" _ Alias "RtlMoveMemory" _ (Destination As Any, _ Source As Any, _ ByVal Length As Long) Function BitCnt(ByVal intVal As Integer) As Long Dim Cnt As Long Dim lngVal As Long Call MoveMemory(lngVal, intVal, 2) 'int型をlong型にキャスト Do While lngVal Cnt = Cnt + (lngVal And 1) lngVal = lngVal \ 2 Loop BitCnt = Cnt End Function

全文を見る
すると、全ての回答が全文表示されます。
  • todo36
  • ベストアンサー率58% (728/1234)
回答No.5

bitシフトもどきの n = n \ 2 を使う。 最上位bitをマスクする必要がある。 Function BitCnt(ByVal n As Long) As Long Dim Cnt As Long If (n And &H80000000) Then Cnt = 1 n = (n And &H7FFFFFFF) End If Do While n Cnt = Cnt + (n And 1) n = n \ 2 Loop BitCnt = Cnt End Function # int型で扱うよりはlong型のほうが早いかも

全文を見る
すると、全ての回答が全文表示されます。
  • terra5
  • ベストアンサー率34% (574/1662)
回答No.4

0~65535までの入力の場合 i = (i And &HAAAA) / 2 + (i And &H5555) i = (i And &HCCCC) / 4 + (i And &H3333) i = (i And &HF0F0) / 16 + (i And &HF0F) i = (i And &HFF00) / 256 + (i And &HFF) アセンブラ向きです。 本来は割り算でなくシフト演算使いますが、.NET以降でないと使えないようでしたので。 最初の式が一回の足し算で実質的に八回の足し算をおこなっているのがポイントです。 これは最初は1bit + 1bit = 2bitとなる計算なので 16bit幅があると2bitの演算を8つ分しています。 次は 2bit + 2bit = 4bit (3bitで十分ですが) 以下同様 条件分岐無し、データのメモリアクセス無し、加算、and、シフトは通常アセンブラ最速の命令ということで、 アセンブラレベルならこの手の方法が多分最速です。 VBだとよくわかりませんが、速い事は確かでしょう。 以前、32bit版をCで使いました。

全文を見る
すると、全ての回答が全文表示されます。
  • bikkuri
  • ベストアンサー率33% (23/68)
回答No.3

処理速度最優先で何回も行うのでしたら、表引きがいいです。 2バイトの値→ビット1の個数の表をあらかじめ 配列で作成しておき、単純に表を参照するだけです。 実際には、2バイト用の表は結構大きいので、1バイト用の 表を作成して、上位バイト、下位バイトで2回参照するのが お勧めかもしれません。 (#1の方のも3ビット毎の表引きですね) 実装の例(動作未確認) private bittab(255) as integer public function bitcount(byval a as long) as integer ・bitcount = bittab(a mod 256) + bittab(a \ 256) end function bitcountを使用する前に、bittab()に0~255まで答えを 初期値として設定しておく必要があります。 (初期値を計算する方法は、従来のシフトなど好きな処理で)

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

好ましいやり方ではないけれども、IFは使いません。 Dim lngTarget As Long Dim lngResult As Long lngResult = ((lngTarget And &H1) <> 0) _ + ((lngTarget And &H2) <> 0) _ + ((lngTarget And &H4) <> 0) _ + ((lngTarget And &H8) <> 0) _ + ((lngTarget And &H10) <> 0) _ + ((lngTarget And &H20) <> 0) _ + ((lngTarget And &H40) <> 0) _ + ((lngTarget And &H80) <> 0) _ + ((lngTarget And &H100) <> 0) _ + ((lngTarget And &H200) <> 0) _ + ((lngTarget And &H400) <> 0) _ + ((lngTarget And &H800) <> 0) _ + ((lngTarget And &H1000) <> 0) _ + ((lngTarget And &H2000) <> 0) _ + ((lngTarget And &H4000) <> 0) _ + ((lngTarget And &H8000) <> 0) Debug.Print lngResult / (True) もうひとつ、あらかじめテーブルを用意しておくやり方も。 Dim lngTarget As Long Dim intBits(256) As Integer intBits(0) = 0 intBits(1) = 1 intBits(2) = 1 intBits(3) = 2 '...略 intBits(255) = 8 lngTarget = lngTarget And &HFFFF& Debug.Print intBits(lngTarget \ 256) + intBits(lngTarget Mod 256)

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ビット演算子について

    あるプログラムの中で下記のようなif文の記述を見かけました。 どういう計算をしてif文の判定を行っているのでしょうか。 (1)256を2進数に変換して → 100000000 (2)0x00000004を2進数に変換して → 100 (3)100000000 & 100 のビットAND演算を行う そもそも(3)で100000000 と 100 では桁数が違うけどどうやって両者でビット演算するので しょうか。100を 000000100というように0を補完して計算すればよいのでしょうか。 その場合、100000000 & 000000100 → 000000000(2進数) → 0(10進数) となりif文の中には入らないことになると思います。 if(256 & 0x00000004 != 0)

  • 2進数データのビット演算

    vb.netにて 0と1からなる2進数で記録した2つの値をビット演算したいと思っております。 Convert.ToInt32("1111101000", 2) などを使って、一度数値に変換して演算すれば、計算可能なことはわかったのですが、計算に利用したいデータが2進数で1000桁ほどあります。桁数が多い場合、Convert.ToInt32ではエラーが出て実行できません。 無数に長い2進数のデータをビット演算するにはどうすればよろしいでしょうか。 ご存知の方、ご教授よろしくお願いいたします。

  • 2進数の計算について

    2進数の計算について分からない問題があるのでお願いします。 (1) 2進5ビットの数値で,01001をバイアス表示とみるとき,10進数ではいくつか (2) 10進数の4を2進5ビットで表す.バイアス表示を用いると,どのように表されるか. できるだけ詳しい回答くれるとありがたいです。

  • 3進展開による有限体上での累乗計算の方法

    僕はペアリング暗号システムを作るために現在有限体上(標数3^97)の楕円曲線の計算プログラムを作成しています。その過程ででてくる数字で、a^((3^97+1)/4)という数字が出てきます。この指数を2進展開してdouble and add法を使って計算していたのですが、この方法だと少し計算速度が遅いのです。 そこで(3^97+1)/4という数字を3進数に直して演算を行えば高速化ができると思いました(標数が3の倍数になるから)が、その計算方法がわかりません。 double and add法のような形での計算方法が知りたいです。知っている方がいたら、是非教えてください。

  • 桁区切り数値の計算

    PHP+MYSQLで 演算子を使って計算をしたいのですが、データーベースから 数値を取り出したときに3桁以上の数値が計算できません。 <?php if($products_teika > 0.0000) { $pacent = round( 100-($products_price / $products_teika) * 100, 0); }else{ $pacent = "-"; } ?> <?php echo $pacent; ?>%OFF! という計算をさせ、割引率を表示させたいのですが 3桁以上になるとうまく計算できません。 このような場合、桁区切りの数値を計算させる方法が あるのでしょうか? ご存知の方ご教授お願いいたします。

    • ベストアンサー
    • PHP
  • エクセル2002の計算式についてですが、

    エクセル2002の計算式についてですが、 例えば下記のような条件で計算式を作りたいのですが、 D5:D17まで空欄だった場合、D18も空欄 D5:D17まで1箇所以上のセルに数値の入力があった場合、 D18に、D5:D17の加算数値を求めたいのですが、 どのような計算式にすればよろしいでしょうか? IF、AND関数を組み合わせれば下記のように一応は出来ますが、 =IF(AND(D5="",D6="",D7="",D8="",D9="",D10="",D11="",D12="",D13="",D14="",D15="",D16="",D17=""),"",SUM(D5:D17)) 仮に、D5:D3000のように範囲が広い場合、 IF、AND関数ではかなりしんどいですが何か良い方法がありますでしょうか?

  • 多倍長演算における実行時間と計算量の差

    数学の論文において数値実験が必要だったため, 多倍長演算をC++で実行したところ,計算量とのギャップが生じました. その原因をコンピュータに詳しい方にアドバイスを頂きたいと思って質問させていただきました. 具体的には,n,m を同ビット として 以下の二つの演算を考えます. 演算(1) n * m 演算(2) n^2 % m (n^2は先に計算しておき,% (mod)の演算のみ) -------------------------------------------------- ■計算量評価 大雑把に(1)と(2)の計算量を比較すると (1) lg n * lg m = (lg n)^2 (2) (2*lg n - lg m) * lg m = (lg n)^2 となるので,(1) と (2)はほぼ同じ計算量となります. -------------------------------------------------- しかしながら,実際に計算をしてみると, n,m が 1000bit ほどまでは,ほぼ同じ計算時間なのですが, 2000bit, 4000bit ,..., と数を大きくしていくと,大きくしただけ (2) の速度が遅くなります. 具体的な実験結果は画像で添付いたします. 画像 (http://puu.sh/6iBQf.png) (1) と (2)の実行時間のギャップは何処から生じたものなのか,何かわかるかたがいらっしゃいましたら教えていただけたら嬉しいです. よろしくお願い致します. 予想:  コンピュータの知識があまりないですが,自分なりの予想では,(2)のn^2という数が大きすぎるため,演算においてメモリ間とのデータのやり取りで何かのオーバーヘッドが生じているのではないかと予想していますが,確証がもてません.

  • 計算結果のみ 0 を表示する方法を教えて下さい。

    計算結果のみ 0 を表示する方法を教えて下さい。 D4に数値が入った場合、D5に13万円未満は0%・13万円以上は1%・14万円以上は2%・尚且下3桁は切り捨てというように次の計算式を設定しています。 ROUNDDOWN(IF(D4<130000,D4*0%,IF(AND(D4>=130000,D4<140000),D4*1%,IF(AND(D4>=140000,D4<180000),D4*2%,))),-3) ゼロ値は表示しないとしていますが、D4に数値が入りD5の計算結果が0であった場合は0を表示したいのです。 D4に数値が入るまではD5は非表示になりD5に数値が入ると0表示になるように設定するにはどうすればいいのでしょうか?

  • フォートランプログラムの計算負荷について

    今、フォートランで数値計算をしています。 プログラムを書き換えて走らせたところ、計算速度が非常に遅くなりました。 考えられるのは、IF文を多く使うようにしたこと、サブルーチンの呼び出し回数をふやしたなどが考えられるのですが。IF文はそれほど、計算負荷の大きいものなのでしょうか。 お願いいたします。

  • if(wp & MK_ LBUTTON)

    case WM_MOUSEMOVE:   if(wp & MK_ LBUTTON) {   x = LOWORD(lp);   y = HIWORD(lp); } if(wp & MK_ LBUTTON)  の wp & MK_ LBUTTON ですが何をやってるんでしょうか? WPARAMと、MK_ LBUTTONの、 ビット演算、AND演算してると思うのですが 具体的どんな」ビット計算が行われているんでしょうか? 教えてください。