Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


1872 / 13645 ツリー ←次へ | 前へ→

【71339】10進数から2進数への高速変換 kein 12/2/22(水) 23:14 質問[未読]
【71340】Re:10進数から2進数への高速変換 kanabun 12/2/23(木) 0:20 発言[未読]
【71341】Re:10進数から2進数への高速変換 ちん 12/2/23(木) 0:34 発言[未読]
【71344】Re:10進数から2進数への高速変換 kanabun 12/2/23(木) 17:11 発言[未読]
【71345】Re:10進数から2進数への高速変換 kein 12/2/23(木) 20:55 お礼[未読]
【71354】Re:10進数から2進数への高速変換 yoko 12/2/24(金) 17:44 発言[未読]
【71355】Re:10進数から2進数への高速変換 ichinose 12/2/24(金) 18:07 発言[未読]
【71360】Re:10進数から2進数への高速変換 kein 12/2/24(金) 23:45 質問[未読]
【71363】Re:10進数から2進数への高速変換 ichinose 12/2/25(土) 1:17 発言[未読]
【71364】Re:10進数から2進数への高速変換 ichinose 12/2/25(土) 1:41 発言[未読]
【71365】Re:10進数から2進数への高速変換 kein 12/2/25(土) 2:05 お礼[未読]
【71367】二箇所訂正です ichinose 12/2/25(土) 11:23 発言[未読]

【71339】10進数から2進数への高速変換
質問  kein  - 12/2/22(水) 23:14 -

引用なし
パスワード
   10進数を2進数に高速に変換したいのですが
何かいい方法は無いでしょうか?

現在は下記のプログラムでバイナリファイルを読み込み2進数に変換という
作業を行っており、buf(i)の要素数は7000程度で、8桁の2進数へ変換しています。
(倍精度浮動小数点フォーマットで保存されているデータの変換
をしているプログラムの一部です。)
For〜Nextのループで1.5sec程度掛かってしまっているのですが
これを出来れば100msec以下に出来ればうれしいです。
作業環境はWin98、EXCEL2000です。
新しいパソコンを使用すれば早くなるのは分かっているのですが
なんとかする方法は無いでしょうか?

sub test()
  Dim inputFileName As String
  Dim inputFn As Long
  Dim buf() As Byte
  Dim X As Long
  Dim Bin_Str() As String

  inputFileName = "C:\data.ini"
  inputFn = FreeFile
  Open inputFileName For Binary As #inputFn
    ReDim buf(LOF(inputFn))
    Get #inputFn, , buf
  Close #inputFn

  FOR i=0 next Ubound(buf)
    X=buf(i)
    Bin_Str(i)=kDec2Bin(X)
  Next
End Sub

Function kDec2Bin(ByVal num As Long) As String
 Dim ss$, ii&, jj&, nn&
 nn = IIf(num < 0, num + 2147483648#, num)
 jj = 7 'jj+1 -> 2進数の桁数
 While Not (-2 ^ jj <= num And num < 2 ^ jj) '桁数を求める
  jj = jj + 8
 Wend
 For ii = 1 To jj
  ss = (nn Mod 2) & ss '2進数の文字列作成 0or1
  nn = nn \ 2
 Next
 kDec2Bin = IIf(num < 0, 1, 0) & ss
End Function

【71340】Re:10進数から2進数への高速変換
発言  kanabun  - 12/2/23(木) 0:20 -

引用なし
パスワード
   ▼kein さん:
>10進数を2進数に高速に変換したいのですが
変換はあまり得手ではないのですが、試しに
16進数表記になおして、この1文字を4ケタの 0/1 に表記しなおす
関数を考えてみました。速くはないかもですが、簡単です (^^

Function toBin(num&) As String
 Dim ss$, i&
 ss = Hex$(num)
 ReDim zz(1 To Len(ss)) As String
 For i = 1 To Len(ss)
   Select Case Mid$(ss, i, 1)
    Case "0": zz(i) = "0000"
    Case "1": zz(i) = "0001"
    Case "2": zz(i) = "0010"
    Case "3": zz(i) = "0011"
    Case "4": zz(i) = "0100"
    Case "5": zz(i) = "0101"
    Case "6": zz(i) = "0110"
    Case "7": zz(i) = "0111"
    Case "8": zz(i) = "1000"
    Case "9": zz(i) = "1001"
    Case "A": zz(i) = "1010"
    Case "B": zz(i) = "1011"
    Case "C": zz(i) = "1100"
    Case "D": zz(i) = "1101"
    Case "E": zz(i) = "1110"
    Case "F": zz(i) = "1111"
   End Select
 Next
 toBin = Join(zz, "")
End Function

【71341】Re:10進数から2進数への高速変換
発言  ちん  - 12/2/23(木) 0:34 -

引用なし
パスワード
   ▼kein さん:こんばんわ、ちんといいます。
10進ー>2進の変換ですが、命令数が少なくなれば、
処理速度が高速になります。
スピードは比較してませんが、参考サイトのプログラミングを添付します。

Private Function Convert10to2(Value As Long) As String

  Dim lngBit As Long
  Dim strData As String

  Do Until (Value < 2 ^ lngBit)
    If (Value And 2 ^ lngBit) <> 0 Then
      strData = "1" & strData
    Else
      strData = "0" & strData
    End If

    lngBit = lngBit + 1
  Loop

  Convert10to2 = strData

End Function

または、

Function DecToBin(ByVal Dec As Long) As String '10進法→2進法
'左からループ変数、桁数、2進法文字列
Dim cnt&, keta&, Bin$
On Error GoTo Trap

'桁数チェック
If Dec < 0 Or Dec >= 2 ^ 32 Then Exit Function '桁数を確認する
For cnt = 0 To 31
  If Dec < 2 ^ cnt Then
  keta = cnt - 1
  Exit For
  End If
Next

'上の位から分解していく
For cnt = keta To 0 Step -1
  Bin = Bin + CStr((Dec \ (2 ^ cnt)) Mod 2)
Next

DecToBin = Bin

Trap:

End Function

2種類UPします。

サイトの検索方法は、vba 2進変換 で、探してみて下さい。

以上、参考までに・・・

【71344】Re:10進数から2進数への高速変換
発言  kanabun  - 12/2/23(木) 17:11 -

引用なし
パスワード
   ▼kein さん:
よくみれば、buf(i) は 1バイトコードで
0〜255までの範囲の数値なんですね
それなら、256種類の2進表記文字列を配列に作っておいて、
それを読み込んだバイト数の要素に置き換えればこれが一番
速いと思いますよ

Sub test2()
  Dim inputFileName As String
  Dim inputFn As Long
  Dim buf() As Byte
  Dim Bin_Str() As String
  Dim i&
  
  '0〜255バイト別2進表記配列
  Dim Bin(0 To 255) As String
  For i = 0 To 255
    Bin(i) = kDec2Bin(i)
  Next

  inputFileName = "C:\data.ini"
  inputFn = FreeFile
  Open inputFileName For Binary As #inputFn
    ReDim buf(1 To LOF(inputFn))
    Get #inputFn, , buf
  Close #inputFn

  ReDim Bin_Str(1 To UBound(buf))
  For i = 1 To UBound(buf)
    Bin_Str(i) = Bin(buf(i))
  Next
End Sub

----- 参考 Speed ---------
test(kDec2Bin)  133

toBin         89
Conv10to2   107
DecToBin    143

test2         8

【71345】Re:10進数から2進数への高速変換
お礼  kein  - 12/2/23(木) 20:55 -

引用なし
パスワード
   ▼kanabun さん、ちんさんありがとうございます。

今日、会社で試していて16進数経由だと1sec.以下になったけど
まだまだ遅いなと思っていたところでした。
また、明日にでも会社で試してみます。

実は作成者不明のdllファイルから関数を呼び出して処理させると
バイナリファイルの読み込み後から浮動小数点フォーマット→数値への変換
までが30msec以下で出来るのでなんとか近い速度で処理させたいと
思っていたところでした。
また、何か質問することがあるかもしれませんがその時はよろしくお願いします。

【71354】Re:10進数から2進数への高速変換
発言  yoko  - 12/2/24(金) 17:44 -

引用なし
パスワード
   ▼kein さん:
>実は作成者不明のdllファイルから関数を呼び出して処理させると
>バイナリファイルの読み込み後から浮動小数点フォーマット→数値への変換
>までが30msec以下で出来るのでなんとか近い速度で処理させたいと
>思っていたところでした。

これは浮動小数点数データのMSBinary形式からIEEE形式への変換とかの事でしょうか?
dllを使わずVBAで処理したいと?
そうであれば具体的な処理内容を示されるとより高速な変換コードの回答があるかもしれません。

【71355】Re:10進数から2進数への高速変換
発言  ichinose  - 12/2/24(金) 18:07 -

引用なし
パスワード
   ▼kein さん:
こんばんは。


>実は作成者不明のdllファイルから関数を呼び出して処理させると
>バイナリファイルの読み込み後から浮動小数点フォーマット→数値への変換
>までが30msec以下で出来るのでなんとか近い速度で処理させたいと
>思っていたところでした。

提示されたコードは、バイナリーファイルから、読み込んだデータを
ビットイメージに変換するコードですよね
(HEXイメージでダンプ表示ってのは、バイナリーエディタなんかで
見かけますけど、珍しいですよね)。
それで興味深い質問だったので投稿したのですが、

このビットイメージに変換するのが最終目的なんですか?
それとも

>浮動小数点フォーマット→数値への変換

と記述されていることから、ここから別の結果を求める
中間結果なのでしょうか?

具体的に教えてください。

【71360】Re:10進数から2進数への高速変換
質問  kein  - 12/2/24(金) 23:45 -

引用なし
パスワード
   ichinose さん
yoko さん

私がやりたいのはIEEE形式倍精度浮動小数点フォーマット(以下、IEEE)で
記録されているバイナリファイルを読み込んで10進数表記のテキストに
変換するということです。

>(HEXイメージでダンプ表示ってのは、バイナリーエディタなんかで
>見かけますけど、珍しいですよね)。
珍しいことだったんですか?インターネットで検索を行いつつ
我流でやっているので実はバイナリファイルの扱いすら
よくわかっていません^^;
バイナリファイルを読み込んだ配列を、Cstr(buf(1))とかで
覗いてやると0〜255の10進数だったので2進数に変換しようと
してました。(この部分を質問していました。)

この後の作業はIEEEは8バイトで現されているので
配列を8ヶほど繋げて、64ビットの2進数にして
1ビット目が符号、2〜12ビット目が指数、13〜64ビット目が仮数
を示しているので指数部分を2進数→10進数に変換。
仮数部分を2進数→10進数として最終的に10進数表記に変換するつもり
だったのですがもしかしてとんでもなく面倒なことしてました?

プログラムが手元に無いためプログラムそのものを貼れなくてすいません。

【71363】Re:10進数から2進数への高速変換
発言  ichinose  - 12/2/25(土) 1:17 -

引用なし
パスワード
   ▼kein さん:

>私がやりたいのはIEEE形式倍精度浮動小数点フォーマット(以下、IEEE)で
>記録されているバイナリファイルを読み込んで10進数表記のテキストに
>変換するということです。
なるほど・・・。

では、こんなコードを実行して試してみてください。

新規ブックの標準モジュールにて、

Sub バイナリファイルの作成()
  Dim dbl(1 To 3) As Double
  Dim fno As Long
  dbl(1) = 0.111
  dbl(2) = 3
  dbl(3) = 4
  '書き込むデータは上記の配列です
  fno = FreeFile
  
  Open ThisWorkbook.Path & "\sample.bin" For Binary As #fno
  Put #1, , dbl()
  Close #fno
End Sub

ThisWorkbook.Path を使っていますから、名前を付けて保存してから、
上記のコードを実行してください。


ブックと同じフォルダ上に sample.binというファイルが作成されます。

バイナリエディタを使えば、中身をHEXイメージで見ることが出来ますから、
見てみてください。

ファイルのプロパティを見れば、サイズが24バイトと表示されているはずです。
当然ですよね? 
倍精度浮動小数点データを3つ書き込んでいますから、
3*8=24バイトですね!!

バイナリエディタで中身をみると、以下のようなHEXイメージが表示されます。

D1 22 DB F9 7E 6A BC 3F 00 00 00 00 00 00 08 40
00 00 00 00 00 00 10 40

いかがですか? 想像したような値ですか?

最初の8バイト(D1 22 DB F9 7E 6A BC 3F)で0.111 という数字を表していることに
なるのですが、最初のハーフバイトは、Dです。2進数では、1101ですね?

>1ビット目が符号
と仰っていましたが、1ですね? 0.111は、正の数なのに・・・。
実は、ディスク上では、逆に記録されているので本当は、

3F BC 6A 7E F9 DB 22 D1 なんです。

これが、0.111なんです。


ですから、Byte変数で読み込んだ場合は、そのまま、
D1 22 DB F9 7E 6A BC 3F の順序で読み込んでしまいますから、

その辺りも考慮しなければなりません。

が、倍精度浮動小数点のデータだけだと分かっているなら・・・、

Sub バイナリファイルの読み込み()
  Dim g0 As Long
  Dim dbl() As Double
  Dim fno As Long
  fno = FreeFile
  Open ThisWorkbook.Path & "\sample.bin" For Binary As #fno
  ReDim dbl(1 To LOF(fno) / 8)
  Get #1, , dbl()
  Close #fno
  For g0 = LBound(dbl()) To UBound(dbl())
    MsgBox g0 & "番目の数字は、  " & dbl(g0)
  Next
  MsgBox "終わり"
End Sub

こんなコードで値は、取得できます。

こういうことですか?

【71364】Re:10進数から2進数への高速変換
発言  ichinose  - 12/2/25(土) 1:41 -

引用なし
パスワード
   追伸

古いシステムからのデータで倍精度浮動小数点の仕組みが
IEEE 754とは異なる場合は前投稿の方法では
正しく値の取得は出来ませんから、違う方法を模索しなければ
なりませんが・・・・。

【71365】Re:10進数から2進数への高速変換
お礼  kein  - 12/2/25(土) 2:05 -

引用なし
パスワード
   ▼ichinose さん
ありがとうございました。
倍精度浮動小数点のバイナリファイルをそのまま
Double型の配列に読み込ませるだけでよかったのですね・・・

なんかとんでもなくアホなことをやっていたってことが
わかりました;;
ネットの検索だよりの完全な我流でやっているので
基本がまったくわかってないのです。

また、何か質問することがあればよろしくお願いします!

P.S.
検算してみましたが大丈夫そうです。

【71367】二箇所訂正です
発言  ichinose  - 12/2/25(土) 11:23 -

引用なし
パスワード
   >  Put #1, , dbl()
  Put #fno, , dbl()

>  Get #1, , dbl()
  Get #fno, , dbl()

freefile関数を使ってる意味がないので訂正です。

1872 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free