byte型のデータをINT型に変更するには?

解決


nosamurai  2007-05-12 20:27:05  No: 98738

はじめまして。
VB 6.0を使用しています。
あるデータをバイナリで開き、ある2バイトのデータをINT型に変更しようと関数を作成したのですが、オーバーフローになることがあります。
関数は、以下の通りです。

Public Function ByteToInt(Low As Byte, Up As Byte) As Integer
    
     ByteToInt = IIf(Up > &H7F, (Low + (CLng(Up) * &H100)) - &H10000,                   Low + (CLng(Up) * &H100))
     
End Function

処理的には、間違ってないような気がするのですが、よろしくお願いします。


魔界の仮面弁士  2007-05-12 20:55:01  No: 98739

> オーバーフローになることがあります。
具体的には、どんな値を渡したときですか?


大吉末吉  2007-05-13 02:37:30  No: 98740

以下の様にして試してみましたが・・・
エラーにはなりませんよ。

-----------------------------------------------
    Dim i As Integer, j As Integer
    For j = 0 To 255
        For i = 0 To 255
            Debug.Print i, j, ByteToInt(CByte(i), CByte(j))
        Next
    Next
-----------------------------------------------

他の部分が原因では?


nosamurai  2007-05-13 11:57:16  No: 98741

ご返答ありがとうございます。
Low 12 UP 144が渡ると、オーバーフローします。


魔界の仮面弁士  2007-05-14 01:19:01  No: 98742

> Low 12 UP 144が渡ると、オーバーフローします。
当方ではオーバーフローしませんでしたが……。
他の部分が原因では?

Option Explicit

Private Sub Form_Load()
    Const L As Byte = 12
    Const U As Byte = 144
    
    Dim result As Integer
    result = ByteToInt(L, U)
    Debug.Print Hex(result)
End Sub

'Private Function ByteToInt(ByVal Low As Byte, ByVal Up As Byte) As Integer
Public Function ByteToInt(Low As Byte, Up As Byte) As Integer
    
     ByteToInt = IIf(Up > &H7F, (Low + (CLng(Up) * &H100)) - &H10000, Low + (CLng(Up) * &H100))
     
End Function


nosamurai  2007-05-16 12:06:02  No: 98743

IIFをIF文に変更すると、なぜかうまく動きました。
ありがとうございました。

あともうひとう質問なのですが、

魔界の仮面弁士さんが記述していただいた

Option Explicit

Private Sub Form_Load()
    Const L As Byte = 12
    Const U As Byte = 144
    
    Dim result As Integer
    result = ByteToInt(L, U)
    Debug.Print Hex(result)
End Sub

'Private Function ByteToInt(ByVal Low As Byte, ByVal Up As Byte) As Integer
Public Function ByteToInt(Low As Byte, Up As Byte) As Integer
    
     ByteToInt = IIf(Up > &H7F, (Low + (CLng(Up) * &H100)) - &H10000, Low + (CLng(Up) * &H100))
     
End Function

を実行すると  resultは-28860となり、"900C"をデバッグしますが、Windowsの関数電卓で16進"900C"を10進に直すと36876を返します。

36876のほうが正しいような気がするのですが…。
できれば36876を取得したいのですが…。

すいません、初歩的な質問で。


魔界の仮面弁士  2007-05-16 18:41:01  No: 98744

その手の変換関数では、ByVal 指定を付けるべきかと。

> resultは-28860となり、"900C"をデバッグしますが、
ん……? そんなハズは無いのですが。値を写し間違えていませんか?

> Windowsの関数電卓で16進"900C"を10進に直すと36876を返します。
Word(16bit 整数型)サイズで 16進数/10進数変換される場合、
符号付き整数型なら -28660、符号無しなら、36876 ですよね。
(関数電卓で、-28660 を16進数変換してみましょう)

符号付きの場合、最上位ビットを「0は正数、1は負数」として扱うので、
16bitサイズの整数型の場合、符号付きか符号無しかによって、
  0000 〜 7FFF  → 0 〜 32767
  8000 〜 FFFF  → -32768 〜 -1 または 32768 〜 65535
という値とみなされます。
今回の -28660 と 36876 の場合、両者はメモリ配置的には同じ値ですので、
それを API 等に渡す分には、どちらの値を使っても同じ結果を得られます。

> できれば36876を取得したいのですが…。
あなたの作成された関数では無理ですよ。戻り値が Integer 型ですから、
-32768〜32767 の範囲までしか返せません。

VB2005 なら、符号無し16bit整数型(UShort)もサポートしていますが、
VB6 にはそれがありませんしね。16bit整数型は符号付きのみです(Integer)。

一応、「Debug.Print &H900C%; &H900C&」の結果からもわかるように、
Long 型で扱うようにすれば、32768 以上の値も扱えます。
ただし型サイズが変化するので、API などに渡す場合には都合が悪くなります。


nosamurai  2007-05-16 22:55:51  No: 98745

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

>ん……? そんなハズは無いのですが。値を写し間違えていませんか
すいません。写し間違えです。

>あなたの作成された関数では無理ですよ。戻り値が Integer 型ですから、
>-32768〜32767 の範囲までしか返せません。
INT型の値範囲を忘れていました。すいません。

> できれば36876を取得したいのですが…。
この関数の帰り値を一度Hex関数で16進に直し、
  &H900C&
といったように、Long型に直そうと思っているのですが可能でしょうか?

CLng("&H" & Hex(ByteToInt()) & "&")
と考えたのですが、無理でした。


nosamurai  2007-05-16 23:23:16  No: 98746

関数そのものをlongのものに書き換え、うまくいきました。
いろいろありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加