人に聞けない痔の悩み、これでスッキリ >>

VBで4byteの数字の上位2バイト、下位2バイトをとりだす方法を教えてください。
以下のコードの8行目で(9行目も同様)オーバーフローしてしまいます。

1 Dim inputData As Double
2
3 Dim d1 As Double
4 Dim d2 As Double
5
6 inputData = 65538 'd1=1, d2=2を期待
7 d1 = inputData And 65535 'FFFFでマスク
8' d2 = inputData And 4294901760# 'FFFF0000でマスク
9 d2 = CDbl(inputData And 4294901760#) 'FFFF0000でマスク

A 回答 (4件)

ようは、32bit符号なし数値を、上位16bitと下位16bitに切り出して符号なしの数値で求めたいということですよね。



Dim inputData As Long
Dim d1 As Long
Dim d2 As Long

inputData = &HFFFFFFF0 '上位と下位がわからなくなるとまずいので変えてあります。

d1 = inputData And &HFFFF&
Dim str As String
str = "00000000" & Hex(inputData And &HFFFF0000)
d2 = "&H" & Left(str, Len(str) - 4)
MsgBox d1 & " " & d2


あとはマスクではなくこんな方法も。
Type typeL
l As Long
End Type
Type typeI
iL As Integer
iH As Integer
End Type


Sub Main()

Dim l As typeL
Dim i As typeI

Dim d1 As Long
Dim d2 As Long

l.l = &HFFFFFFF0

LSet i = l
d1 = "&H" & Hex(i.iL)
d2 = "&H" & Hex(i.iH)

MsgBox d1 & " " & d2
End Sub
    • good
    • 1
この回答へのお礼

ありがとうございました。
いろんな解法があるんですね。
Typeははじめてみました。
ありがとうございました。

お礼日時:2005/03/16 17:23

こんな感じでどうでしょう?



Dim inpData As Long
Dim d1 As Long
Dim d2 As Long
Dim dh

'inpData = &HFFFFFFFF
inpData = 65538
dh = Right("00000000" & Hex(inpData), 8)
d1 = Val("&H" & Left(dh, 4))
d2 = Val("&H" & Right(dh, 4))
If d1 < 0 Then d1 = d1 + 65536
If d2 < 0 Then d2 = d2 + 65536
'Debug.Print d1
'Debug.Print d2
    • good
    • 0
この回答へのお礼

String型を介するんですねぇ!
"00000000"をつけるのもポイントですね。
目から鱗です。勉強になりました。
ありがとうございました。

お礼日時:2005/03/16 17:21

>説明不足でしたが、4byteというのは、符号なし4byteのことなのです。



符号はあってもなくてもビット操作をするのなら関係ないです。Double等のサイズが違うものを使用するほうがよっぽど問題です。


>inputDataに&FFFFFFFFを代入した時点でオーバーフローしてしまいます。

16進数にすればオーバーフローしません。
で、&FFFFFFFFではなく&HFFFFFFFFです。

#VB6で確認してます。


で、やりたいことってなんですか?

>d1=65535
>d2=65535
>を取得したいのです。

下位16bitを符号なし整数で取得したいのでしょうか?そうすると、今度はd1とd2の違いがわからないのですが。

この回答への補足

>16進数にすればオーバーフローしません。
そうだったんですね。下手に10進に直して代入したのが間違いの基でした。

>#VB6で確認してます。
お時間割いていただき感謝してます

>>d1=65535
>>d2=65535
>>を取得したいのです。
>
>下位16bitを符号なし整数で取得したいのでしょうか?そうすると、今度はd1とd2の違いがわからないのですが。
補足は、MAX(&HFFFFFFFF)を例にあげてしまったので、d1とd2が同じ値になりますが、
&H00010002の場合に、
d1=2(下位2バイト)
d2=1(上位2バイト)
となることを期待しています。

>で、d2って、2じゃなくて&H00010000ですよね?
ではありません。&H0001です。
&HFFFFFFFFの場合には、d2に-65536ではなく
d1=65535(下位2バイト)
d2=65535(上位2バイト)
となることを期待しています。

補足日時:2005/03/16 15:32
    • good
    • 0

>6 inputData = 65538 'd1=1, d2=2を期待



おかしくありません?Doubleなんですよね。
浮動小数ですよ。こんなマスクのかけ方はだめですよね。



型はLongで、マスクは16進数で書きましょう。
また、&HFFFFだとInteger(16bit)になってしまうので、
&HFFFF&としてLong(32bit)にしましょう。


Dim inputData As Long

Dim d1 As Long
Dim d2 As Long
d1 = inputData And &HFFFF&
d2 = inputData And &HFFFF0000

で、d2って、2じゃなくて&H00010000ですよね?

この回答への補足

ご指摘ありがとうございました。
説明不足でしたが、4byteというのは、符号なし4byteのことなのです。
最大、0xFFFFFFFFを10進で4294967295とみなして、
d1=65535
d2=65535
を取得したいのです。
なので、教えていただいた方法では
inputDataに&FFFFFFFFを代入した時点でオーバーフローしてしまいます。
VBにはunsignedの型がないため、Doubleを使おうと考えました。

>で、d2って、2じゃなくて&H00010000ですよね?
ご指摘どおり、d1とd2が逆でした。
求めたいのは上位2byteと下位2byteなので、最後にシフトしないとだめですね。

補足日時:2005/03/16 13:29
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QVBAで符号無し整数

BMPファイルを読み込んで配列に書き出すプログラムを作ろうとしています。
BMPファイルの構造は
http://www.geocities.co.jp/Playtown-Knight/6845/sd_doc/format_windib.html

のページに書かれてあるのですが、
typedef unsigned short WORD
typedef unsigned long DWORD
typedef unsigned char BYTE
typedef long LONG

などの「符号無し整数」で定義された変数を使う必要があります。


http://homepage1.nifty.com/rucio/main/kiso/DataType.htm

のページにあるようにVBではUlongやUshortが使えるようなのですが、

VBA上で

Dim bfSize As ULong


とすると、「ユーザー定義型は定義されていません」
と表示されます。

参照設定のところで何か設定を行えば良いと思うのですがどこを設定すれば良いのでしょうか?


もし、使えないとして、VBAで2バイトや4バイトを数値として読み込むにはどうすれば良いでしょうか?

BMPファイルを読み込んで配列に書き出すプログラムを作ろうとしています。
BMPファイルの構造は
http://www.geocities.co.jp/Playtown-Knight/6845/sd_doc/format_windib.html

のページに書かれてあるのですが、
typedef unsigned short WORD
typedef unsigned long DWORD
typedef unsigned char BYTE
typedef long LONG

などの「符号無し整数」で定義された変数を使う必要があります。


http://homepage1.nifty.com/rucio/main/kiso/DataType.htm

のページにあるようにVBではUlongやUshor...続きを読む

Aベストアンサー

http://support.microsoft.com/kb/189323/ja

参考にしてみてください。

Q16進数の変換処理

VisualBasic6.0で
Val("&H" & "F")
を実行すると、15

Val("&H" & "FF")
を実行すると、255

Val("&H" & "FFF")
を実行すると、4095

Val("&H" & "FFFF")
を実行すると、-1

Val("&H" & "FFFFF")
を実行すると、1048575

という結果が得られます。

なぜ”FFFF”の時に”-1”が返ってくるのでしょうか?
また、どうやったら、
”FFFF”から”65535”が得られるのでしょうか?

教えてください。
よろしくお願いします。

Aベストアンサー

VAL関数
指定した文字列に含まれる数値を適切なデータ型に変換して返します。

FFFFは、INT型で扱える最大値なのでINT型と判定されます。
cint("&H"+"FFFF")だと、-1が返ります。
FFFFFは、INTの扱える値を超えたのでLONG型で判定される為に1048575と言う結果になるのです。
では、なぜマイナスになるのか?
FFFFを2進数で表すと以下のようになりますね。
11111111 11111111 11111111 11111111
↑先頭の1バイト目が1だとマイナスとして扱われます。

以上です。

QVBでファイルが開かれているかどうかを確認したい

お疲れ様です。

Open ステートメントで開いたファイルが、閉じていなければ閉じると言う処理をしたいのですが、ファイルが開きっぱなしかどうかを確認するには、どんな方法があるのでしょうか?

よろしくお願いします。

Aベストアンサー

こんにちは

もう一度同じファイルを同じファイルNo.(#1)で
開きに行くと、
開きっぱなしなら“すでに開いています”とエラーになって
閉じていたら、エラーがないので
判断出きるはずです。

Q16進数を10進数に変換する方法...

お初にお目にかかります(^^)
簡潔に質問しますm(_ _)m

バージョン:MS-Visual Basic6.0
質問内容:
16進数を10進数に変換する方法がわかりません。
Hex(Text1.Text) や Oct(Text1.Text) のような方法で
16進数・8進数に変換できるんですが…
10進数に変換する方法がわかりません。

P.S できれば、16進数→10進数、16進数や10進数→2進数
…に、変換する方法も、よろしければ教えてくださいませ
m(_ _)m

Aベストアンサー

16進数→10進数は

Dim StrHex As String
Dim intVal As Integer
StrHex = "1A"
intVal = Val("&H" & StrHex)

で出来ます。


申し訳ありませんが2進数への変換はよく分かりません。

Q1バイト文字の上位4ビット・下位4ビットの入れ替え方法を教えて下さい

あるパスワードをテキストファイルに書き込む処理です。
そのままだと、パスワードの意味が無いので、上位4ビットと下位4ビットを入れ替えて保存しようと思います。
上位・下位それぞれ4ビットシフトするところまでは出来ました。

 Dim a As Integer
 Dim a1 As Integer
 Dim a2 As Integer
 a = Asc("a")
 a1 = a \ 2 ^ 4
 a2 = a * 2 ^ 4
 MsgBox (Hex(a1))
 MsgBox (Hex(a2))

が、それを8ビットに戻す方法が分かりません。
また、パスワードは1バイト文字による文字列ですが、文字列長分を1バイトずつバッファに読み込んで、変換し、同サイズのバッファに詰め込んでいく処理も分かりません。
以前、MS-C(MSDOS上のC言語)を少しやったので、それでなら分かるのですが、VBは全くの初心者で、調べても調べても見当がつきません。
どうか教えて下さい。
宜しくお願い致します。

Aベストアンサー

●1バイト文字の上位4ビット・下位4ビットの入れ替え
参考。理解・確認のため余分なものを入れている。
骨子は*****のところ。
Sub test01()
h = Array("0", "1", "2", "3", "4", "5", "6", "7", "8", _
"9", "A", "B", "C", "D", "E", "F")
a = Asc("z")
MsgBox "コード" & a
x = a Mod 16 '*****
y = Int(a / 16) '*****
MsgBox "16進表示" & h(x) & " " & h(y)
'もとの数のビット列
s = ""
x = a
For i = 1 To 8
y = x Mod 2
s = y & s
x = Int(x / 2)
Next i
MsgBox "もとの数のビット列" & s
'----
'上位・下位4ビット反転
x = a Mod 16
y = Int(a / 16)
z = x * 16 + y '*****
MsgBox "上位・下位4ビット反転のコード" & z
x = z Mod 16
y = Int(z / 16)
MsgBox "16進表示" & h(x) & " " & h(y)
'------上位・下位4ビット反転のビット列
s = ""
x = z
For i = 1 To 8
y = x Mod 2
s = y & s
x = Int(x / 2)
Next i
MsgBox "上位・下位4ビット反転" & s
End Sub
●文字列長分を1バイトずつバッファに読み込んで、変換し、同サイズのバッファに詰め込んでいく処理も分かりません
上記でもやってますが、
S=""
For i=1 to 文字列長
Xには1バイト分上位・下位4ビット反転した結果を入れる
S=S & X
Next i
を使えば良いです。
下位桁から処理なら
S= X & S
にする。

●1バイト文字の上位4ビット・下位4ビットの入れ替え
参考。理解・確認のため余分なものを入れている。
骨子は*****のところ。
Sub test01()
h = Array("0", "1", "2", "3", "4", "5", "6", "7", "8", _
"9", "A", "B", "C", "D", "E", "F")
a = Asc("z")
MsgBox "コード" & a
x = a Mod 16 '*****
y = Int(a / 16) '*****
MsgBox "16進表示" & h(x) & " " & h(y)
'もとの数のビット列
s = ""
x = a
For i = 1 To 8
y = x Mod 2
s = y & s
x = Int(x / 2)
Next i
MsgBo...続きを読む

QVBA2005 16進を2桁で表示したい。

タイトル通りなのですが、

If shtDiff > 1 Then
intNumber = intNumber + 1
ElseIf shtDiff < 1 Then
intNumber = intNumber - 1
End If

intNumberの所に-1が入っているのを確認した後、
strNumber = Format(Hex(intNumber), "00")
とすると表記が"00"になります。
恐らくここの書き方が悪いのだと思うのですが、
Hex(number)だけだと
-1が"FFFF"
-2が"FFFE"になっているのは確認できたのですが、、、
Mid(number,1,2)としても良いのですが、もっとスムーズな方法がありましたら、教えてください!

Aベストアンサー

基本的に HEXステートメントは16進数値を返しますが、桁数を揃える機能はありません。

なので1~15であれば HEX(10) などとすると A のように一桁で帰ってきてしまいますし、257以上の数値を入れれば3桁になります。

またHEXステートメントで返されるのは文字列(正確にはバリアント型)なので、FORMAT文では正常にフォーマットする事は出来ません。

従って常に二桁に桁数を揃えるのであれば
RIGHT("0" & HEX(intNumber),2)
とかきます。4桁であれば RIGHT("000" & HEX(intNumber),4)です。


なお例題の Format(Hex(intNumber), "00") ですと、10~15の値は一桁にしかなりません。

この書き方で二桁になっている様に見えるのは、

HEX(intNum)→0~FFFFの文字列(バリアント型)を返す → A~Fが含まれていない場合は数値として扱えるので、数値に暗黙のキャストをする → FORMATで桁数を合わせる

という流れになっているからです。

従いましてA~Fが含まれている場合は文字列扱いなので、FORMAT文はきいていないことになります。

ただ私はVBA2005で確認した訳ではないのですが、VB系の動作ですと -1 をその書式で実行すると普通はFFFFと返ってくる気がしますね……。

さてVBのiniで表現出来る値は16ビットです。

従いまして -1 を記載した場合 ビット表記すると 1111111111111111 …… という訳で FFFFになります。

これを強制的に二桁に合わせてしまうとFF ですが、これですと255(FF)との区別がつきません。

従いましてマイナスを表記するなら最低4桁にする必要があります。

以上です。

基本的に HEXステートメントは16進数値を返しますが、桁数を揃える機能はありません。

なので1~15であれば HEX(10) などとすると A のように一桁で帰ってきてしまいますし、257以上の数値を入れれば3桁になります。

またHEXステートメントで返されるのは文字列(正確にはバリアント型)なので、FORMAT文では正常にフォーマットする事は出来ません。

従って常に二桁に桁数を揃えるのであれば
RIGHT("0" & HEX(intNumber),2)
とかきます。4桁であれば RIGHT("000" & HEX(intNumber),4)です。


...続きを読む

QEXCELでの16進数取り出し、上位桁と下位桁取り

恐れ入ります。詳しい方教えてください。

各セルに2000までの数値があるデータがあり、このデータを16進数表記で、上位2桁と下位2桁に分けたいと考えています。

例)
870  → &h03, &h66 (870は10進数で366が16進数、これを&hを付けて03と66に分けたい)
1926 → &h07, &h86 

="0x"&DEC2HEX(C4, 4)を使って16進数4桁にすることまでは調べたのですが、上位2桁、下位2桁に分けられず悩んでいます。

Aベストアンサー

いくつか方法はあるでしょうが、
A1に870があるとして
4桁固定でいいなら
上位2桁
=LEFT(DEC2HEX($A1,4),2)
下位2桁
=RIGHT(DEC2HEX($A1,4),2)

QForm_Load と Form_Activate のタイミング

あるデータ入力アプリを作っています。
親フォーム(Form0)で番号を決め、子フォーム(Form1,Form2,Form3,Form4) でデータ入力し、それぞれの子フォームを出るとき(Unload Me) に、変数にsaveしています。それを親フォーム(Form0)で登録を選択したとき、入力データをチェックしてDBに格納しています。
すでにDB格納済のデータの場合、親フォームでDBから変数に読み込み、子フォームのForm_Loadで展開しています。
そこで困っているのは、親と子のフォームを行き来するときにデータの表示で前のが残っていたり、消えてしまったりします。
Form_LoadとForm_Activateを通過するタイミングが、ちゃんと理解できていないためコードの記述位置が不適切なのだと思います。

Form_Load と Form_Activate の実行タイミングについて、お教えください。

Aベストアンサー

Form_Loadは、フォームがロードされたときです。
ロードされる条件は、
1.フォームがスタートアップに指定されているとき、アプリが実行された直後。
2.Show メソッドが呼ばれたとき
3.Loadメソッドが呼ばれたとき
4.フォームに貼り付けられたコントロールのプロパティが参照されたとき
5.フォームに貼り付けられたコントロールのメソッドが呼ばれたとき
です。

ただし、一度ロードされると、Unloadされるまで呼ばれません。


Form_Activateは、フォームがアクティブになったとき、つまり、キャプション(ウィンドウのタイトルバー)の色が変わったときです。

QEXCELファイルのカレントフォルダを取得するには?

EXCELファイルのカレントフォルダを取得するには?

C:\経理\予算.xls

D:\2005年度\予算.xls

EXCEL97ファイルがあります。

VBAで
  カレントフォルダ名
(C:\経理\,D:\2005年度\)
を取得する事は可能でしょうか?

CURDIRでは上手い方法が見つかりませんでした。

Aベストアンサー

こんばんは。
Excel97 でも、同じですね。以下で試してみてください。

Sub test()
'このブックのパス
a = ThisWorkbook.Path
'アクティブブックのパス
b = ActiveWorkbook.Path
'Excelで設定されたデフォルトパス
c = Application.DefaultFilePath
'カレントディレクトリ
d = CurDir
MsgBox "このブックのパス   : " & a & Chr(13) & _
   "アクティブブックのパス: " & b & Chr(13) & _
   "デフォルトパス    : " & c & Chr(13) & _
   "カレントディレクトリ : " & d & Chr(13)
End Sub

Qなぜオーバーフローになるのでしょうか。

VB6です。 こんな現象初めてでびっくりしました。
変数A、h、mはLong型です。
A = 9 * 3600 + 54 * 60 ->オーバーフロー発生

A = 35640 ->オーバーフローにならない

h = 9 : m = 54
A = h * 3600 + m * 60 ->オーバーフローにならない

変数ではなく、実数で計算するとオーバーフローする意味がわかりません。また、計算結果を直接実数で代入した場合、なぜオーバーフローは
発生しないのかも意味不明です・・・

なぜ、オーバーフローが発生したりしなかったりするのでしょうか。

Aベストアンサー

何の指定もなく実数(整数)で計算を行うとInteger型で
計算されるからです。

A = CLng(9) * CLng(3600) + CLng(54) * CLng(60)
または
A = CLng(9 * 3600) + CLng(54 * 60)
として下さい。


人気Q&Aランキング