バイナリ配列 → 整数変換

解決


コナコナ  2009-08-09 00:12:01  No: 142373  IP: 192.*.*.*

初めて質問させていただきます。

VB 5.0です。

バイナリ配列から2バイトを数値として読みたいのですが、
うまくいきません。

    Dim aa(1) As Byte
    Dim n As Integer

    aa(0) = &HFF
    aa(1) = &HFF

    n = Val("&H" & aa(0) & aa(1))

この時、n = 65535 となるようにしたいのですが、
n = -1 となってしまいます。

どのようにすれば良いのでしょうか。
ご教授願います。

編集 削除
GOD  2009-08-09 01:01:58  No: 142374  IP: 192.*.*.*

Integer は-32768〜32767しか表せないから65535は範囲外です。
「Dim n As Long」でどうですか?(環境ないから未確認)

編集 削除
コナコナ  2009-08-09 09:23:40  No: 142375  IP: 192.*.*.*

GODさん

回答ありがとうございます。

longで試してみましたが、n = 2445909 になってしまいます。

編集 削除
魔界の仮面弁士  2009-08-09 22:17:07  No: 142376  IP: 192.*.*.*

>>> aa(0) = &HFF
これは、
  aa(0) = 255
と同義である事に注意してください。
10進数で表記しようと、16進数で表記しようと、
それが指し示す値は同じ数値を意味します。


そして、それに続く
  n = Val("&H" & aa(0) & aa(1))
という処理は、結局のところ
  n = Val("&H" & CStr(255) & CStr(255))
として扱われることになります。ゆえに、この Val 関数は
  n = &H255255
として処理され、「n = 2445909」という値になります。


>> 「Dim n As Long」でどうですか?
Debug.Print CInt("&HFFFF")   '-1
Debug.Print CLng("&HFFFF")   '65535 
になりますね。


> n = 65535 となるようにしたいのですが、
例えば、
  Dim aa(1) As Byte
  aa(0) = &HFF
  aa(1) = &HFF
  n = aa(0) * &H100& + aa(1)
のようにすれば OK です。もし、"FF" という16進数表記からの変換を求めるなら
  Dim aa(1) As String
  aa(0) = "FF"
  aa(1) = "FF"
  n = CLng("&H" & aa(0) & aa(1))
とか、
  Dim aa(1) As Byte
  aa(0) = &HFF
  aa(1) = &HFF
  n = CLng("&H" & Hex(aa(0)) & Hex(aa(1)))
のように記述すれば OK かと。

編集 削除
GOD  2009-08-09 23:58:26  No: 142377  IP: 192.*.*.*

やっと発掘に成功しました。(VB6だけどw)
魔界の仮面弁士 さんフォローありがとうございます。
私は別アプローチということでValを使ったやり方を。
n = Val("&H" & Hex(bytBuf(0)) & Hex(bytBuf(1)) & "&")
↑のように16進文字に変換結合後、最後に"&"をつけてLong型であることを
明示すればご希望の動作になりますよ。(最後に"&"を連結しないと-1になりま
す。)

編集 削除
しんご  2009-08-10 05:04:55  No: 142378  IP: 192.*.*.*

質問が気になって調べていたら、
既にGODさん、魔界の魔界の仮面弁士 さんから良回答がっ!

1つ気になった点をば。
魔界の仮面弁士さんの回答にあります

n = CLng("&H" & Hex(aa(0)) & Hex(aa(1)))

は aa(1) が &HFF 固定(もしくは16進数2桁)時に有効です。
仮に aa(1) が &H1 〜 &HF になる可能性がある場合、
16進数の10の位を考慮しないと仕様によっては
いけないかもしれません。

考慮するのであれば

n = CLng("&H" & Hex(aa(0)) & Right$("0" & Hex(aa(1)),2))

でよいかと思います。

例えば、aa(0) = &H10 , aa(1) = &H1 の場合
CLng("&H" & Hex(aa(0)) & Hex(aa(1)))  →  &H101 →  257
CLng("&H" & Hex(aa(0)) & Right$("0" & Hex(aa(1)),2))
→  &H1001 →  4097

となります。

先に書きましたが、仕様上「257にしたい」となれば
魔界の仮面弁士さんの回答が正しいことになります。

希望する仕様で使い分けてください。


余談
GODさんの回答の補足説明

◆  & を付与しない場合  →  Integer 型で処理されます

&H1 〜 &H7FFF  →  1 〜 32767
&H8000 〜 &FFFF →  -32768 〜 -1 

となります。最上位桁が8〜Fの場合は負の整数として扱われます。
もうおわかりでしょうが、n = -1となった理由はこれです。

◆  & を付与した場合  →  Long 型で処理されます

&H1 〜 &H7FFFFFFF  →  1 〜 2147483647
&H80000000 〜 &FFFFFFFF →  -2147483648 〜 -1 

となります。こちらも最上位桁が8〜Fの場合は
負の整数として扱われます。

以上

編集 削除
魔界の仮面弁士  2009-08-10 10:45:41  No: 142379  IP: 192.*.*.*

> 仮に aa(1) が &H1 〜 &HF になる可能性がある場合、
> 16進数の10の位を考慮しないと仕様によっては
おお、うっかりしていました。フォロー感謝。


> &H1 〜 &H7FFFFFFF  →  1 〜 2147483647
> &H80000000 〜 &FFFFFFFF →  -2147483648 〜 -1 
ちなみに oleaut32.dll のバージョンによって、より長い桁数の16進数値も扱えるようです。
どのバージョンでも問題なく使えるのは、8桁まで(Long型の上限)のようですけれども。


Debug.Print CDec("&H7FFFFFFFFFFFFFFD")    ' 9223372036854775805
Debug.Print CDec("&H7FFFFFFFFFFFFFFE")    ' 9223372036854775806
Debug.Print CDec("&H7FFFFFFFFFFFFFFF")    ' 9223372036854775807
Debug.Print CDec("&H8000000000000000")    '-9223372036854775808
Debug.Print CDec("&H8000000000000001")    '-9223372036854775807
Debug.Print CDec("&H8000000000000002")    '-9223372036854775806
'                         :
Debug.Print CDec("&HFFFFFFFFFFFFFFFD")    '-3
Debug.Print CDec("&HFFFFFFFFFFFFFFFE")    '-2
Debug.Print CDec("&HFFFFFFFFFFFFFFFF")    '-1

編集 削除
コナコナ  2009-08-22 18:10:01  No: 142380  IP: 192.*.*.*

遅くなってしまい、大変申し訳ありません。

GODさん、魔界の仮面弁士さん、しんごさん
どうもありがとうございました。

とても勉強になりました。
これからもよろしくお願いします。

編集 削除