• ベストアンサー

マスクをとるとオーバーフローします

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でマスク

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.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

yumi-mika
質問者

お礼

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

その他の回答 (3)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

こんな感じでどうでしょう? 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

yumi-mika
質問者

お礼

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

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>説明不足でしたが、4byteというのは、符号なし4byteのことなのです。 符号はあってもなくてもビット操作をするのなら関係ないです。Double等のサイズが違うものを使用するほうがよっぽど問題です。 >inputDataに&FFFFFFFFを代入した時点でオーバーフローしてしまいます。 16進数にすればオーバーフローしません。 で、&FFFFFFFFではなく&HFFFFFFFFです。 #VB6で確認してます。 で、やりたいことってなんですか? >d1=65535 >d2=65535 >を取得したいのです。 下位16bitを符号なし整数で取得したいのでしょうか?そうすると、今度はd1とd2の違いがわからないのですが。

yumi-mika
質問者

補足

>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バイト) となることを期待しています。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

>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ですよね?

yumi-mika
質問者

補足

ご指摘ありがとうございました。 説明不足でしたが、4byteというのは、符号なし4byteのことなのです。 最大、0xFFFFFFFFを10進で4294967295とみなして、 d1=65535 d2=65535 を取得したいのです。 なので、教えていただいた方法では inputDataに&FFFFFFFFを代入した時点でオーバーフローしてしまいます。 VBにはunsignedの型がないため、Doubleを使おうと考えました。 >で、d2って、2じゃなくて&H00010000ですよね? ご指摘どおり、d1とd2が逆でした。 求めたいのは上位2byteと下位2byteなので、最後にシフトしないとだめですね。

関連するQ&A

  • 変数への数式の代入でオーバーフローします

    Dim lngDaySec as Long lngDaySec = 60 * 60 * 24 以上のコードでオーバーフローします。 しかし、2行目を以下のように書き換えると lngDaySec = Clng(60 * 60) * 24 正常に値が代入されます。 Long型の値の範囲は「-2,147,483,648 ~ 2,147,483,647」 となっており、「60×60×24」は「86,400」だから 範囲を逸脱しているとは思えません。 どうしてオーバーフローするのでしょうか? そして、Clng関数で回避できるのはなぜなんでしょう? ひょっとしたらアホな質問をしているのかもしれませんが、 どなたかご回答いただければありがたいです。

  • 2013VBでオーバーフローエラー(2)

    よろしくお願いします。 前回の質問ではエラーの出た部分しか表示していなかった為、回答して頂いた方に 十分な情報が提供できずすみませんでした。 下記がエラーの出た部分までの全プログラムです。 Dim book1 As String 'ブック名1 Dim book2 As String 'ブック名2 Dim book3 As String 'ブック名3 Dim book4 As String 'ブック名4 Dim myday As Date Dim ITI1 As String 'アドレスの格納 Dim ITI2 As String 'アドレスの格納 Dim ITI3 As String 'アドレスの格納 Dim ITI4 As String 'アドレスの格納 Dim ITI5 As String Dim ITI6 As String Dim ITI7 As String Dim ITI8 As String Dim myRange As Range 'コードの個数 Dim myRange1 As Range Dim answer As Integer Dim bunki1 As Integer Dim c As Double 'カウント Dim n As Double 'カウント 'ワークブックの設定 Workbooks("A.xls").Activate book1 = Worksheets("ブックシート設定").Range("c3") 'コピー元 'book2 = Worksheets("ブックシート設定").Range("c5") book3 = Worksheets("ブックシート設定").Range("c7") 'A 'book4 = Worksheets("ブックシート設定").Range("c9") bunki1 = Worksheets("ブックシート設定").Range("c16") myday = Worksheets("ブックシート設定").Range("c14") 'コピー元非表示を表示にする Workbooks(book1).Activate Sheets("B").Select Sheets("B").Select Columns("G:J").Select Selection.EntireColumn.Hidden = False Columns("j:q").Select Selection.EntireColumn.Hidden = False 'コードの個数を数える Workbooks(book1).Activate Sheets("B").Select ITI4 = Range("b65536").End(xlUp).Address '----b列の最終行から上方向の終端セルを選択 Set myRange = Worksheets("B").Range("b6", ITI4) answer = Application.WorksheetFunction.Count(myRange) Set myRange1 = Worksheets("B").Range("e8") For c = 1 To answer 'データー個数のカウント If myRange1.Offset(c) = myday Then n = n + 1 Next 'オーフィルターの設定 Workbooks(book1).Activate Sheets("B").Select ITI1 = Range("b65536").End(xlUp).Address '----b列の最終行から上方向の終端セルを選択 ITI7 = Range(ITI1).Offset(, 11).Address Range("a8", ITI7).AutoFilter FIELD:=5, Criteria1:=Format(myday,"yyyy/m/d") >>>>>ここでオーバーフローエラー 前回指摘されたCriteria1:=mydayをCriteria1:=Format(myday,"yyyy/m/d") に追加変更しました。 読みにくいかもしれませんがよろしくお願いします。

  • 1バイト文字の上位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は全くの初心者で、調べても調べても見当がつきません。 どうか教えて下さい。 宜しくお願い致します。

  • プログラミングvbについて質問

    vb2012です。たとえば dim D as double D=1/3 label1.text=D としたときに、label1のテキストが0.333333333333333らへんで止まってしまうのですが、これはどうすればいいでしょうか。

  • 直線と傾きのある楕円の交点を求めたい

    直線と傾きのある楕円の交点を求めたい http://www17.ocn.ne.jp/~lite/pro97doc.html#TOP こちらを参考にさせて頂き、直線と楕円の交点を求める関数を作成しております。 傾きを持たない楕円と直線の交点はこれで求められたのですが、 楕円に傾きがある場合、うまく交点を求められません。 どなたか足りない計算、誤っている箇所等お教え願えないでしょうか。 pt1 :線の始点 pt2 :線の終点 center :楕円の中心座標 radius :楕円の半径 angle :楕円の角度(傾き) henpei :楕円の扁平率 '直線の勾配を求める Dim m As Single = (pt2.Y - pt1.Y) / (pt2.X - pt1.X) '扁平率(ここはかならず長辺/短編?) Dim w As Double = henpei / 100 '楕円の傾き(ラジアン) Dim radian As Single = angle * (Math.PI / 180) '参考元のaとbの長さを求める? Dim a1 As Single = center.X '原点Xからの中心Xまでの距離 Dim b1 As Single = center.Y '原点Yからの中心Yまでの距離 Dim A As Double = CDbl((m ^ 2) + (w ^ 2)) Dim B As Double = CDbl(-2 * (m ^ 2) * pt1.X + 2 * m * (pt1.Y - b1) - 2 * a1 * (w ^ 2)) Dim C As Double = CDbl((m ^ 2) * (pt1.X ^ 2) - 2 * m * (pt1.Y - b1) * pt1.X + ((pt1.Y - b1) ^ 2) - (radius * w) ^ 2 + (a1 * w) ^ 2) Dim D As Double = CDbl((B ^ 2) - (4 * A * C)) '交点無し If D < 0 Then Return crossPoints '2点を求める Dim x1 As Single = CSng((-B + Math.Sqrt(D)) / (2 * A)) Dim y1 As Single = pt1.Y + m * (x1 - pt1.X) Dim x2 As Single = CSng((-B - Math.Sqrt(D)) / (2 * A)) Dim y2 As Single = pt1.Y + m * (x2 - pt1.X)

  • VBAでの演算。オーバーフローしてしまいます

    VBAで現在プログラミングを勉強しています。 除数を利用し数値を割り出したいのですが、どうしてもオーバーフローしてしまいます。 Variant型にすればいいのかなと思い、全てVariant型で最入力したのですが、 上手く動きません。 整数と整数を割り算し、小数の答えが出ます。 それを小数点第2位まで丸めることをしたいと思っています。 どなたが助けていただけませんか、よろしくお願い致します。 以下、入力値です。 Dim ColumnB As Double, ColumnF As Long, ColumnI As Long ColumnB = ColumnI / ColumnF ColumnB = Application.WorksheetFunction.RoundDown(ColumnB, 2) With ThisWorkbook.Worksheets("COVER") .Range("B" & curRow) = ColumnB .Range("F" & curRow) = ColumnF .Range("I" & curRow) = ColumnI End With よろしくお願い致します。

  • VBAでF(I) = 1# / Exp(TT)の値がセルに0と表示され

    VBAでF(I) = 1# / Exp(TT)の値がセルに0と表示されてしまう問題があります。 TTやExp(TT)の値はそれなりの数値がでるのですが、F(I) だけが0となってしまいます。 どうのようにすれば正しくひょうじされるでしょうか? また、CDblの位置は下記の場所であっているのでしょうか? 以上ご回答よろしくお願いします。 Private Sub CommandButton1_Click() Dim X(500) As Double Dim Y(500) As Double Dim F(500) As Double Dim FI(500) As Double Dim N As Integer Dim DX As Double Const Pi = 3.141592654 Dim I As Integer Dim TT As Double N = Range("_N") DX = Range("_DX") '-----------------------<データを自動生成している。ここから F(1) = 0.5 For I = 2 To N TT = DX * CDbl(I - 1) F(I) = 1# / Exp(TT) Next I '-----------------------<データを自動生成している。ここまで Worksheets("Sheet1").Range("E4:E30").Value = TT Worksheets("Sheet1").Range("F4:F30").Value = Exp(TT) Worksheets("Sheet1").Range("G4:G30").Value = F(I) End Sub

  • 小数点の引き算が不正確

    みなさまこんばんわです。よろしくお願い申し上げます。 VB.NET 2008でFunctionプロシージャを作っています。 その内容は、Double型の値を与えると、その小数点第一位のみをInteger型で返すというものです。 たとえば、3.142を与えると、1を返します。38.98を与えると、9を返します。 これを次のようにコーディングしました。コメントは、39.9を与えたときの動作です。答えは、9を期待しますよね。 ------------------------------------- Function SyosutenWoKaesu(ByVal NyuuryokuSuuchi As Double) As Integer Dim SyosutenBubun As Double Dim SeisuuBu As Integer SeisuuBu = Fix(NyuuryokuSuuchi) 'Fix関数は、入力数値の整数部を返すので、39をInteger型で返します SyosutenBubun = NyuuryokuSuuchi - CDbl(SeisuuBu) 'データ型をDouble型に変換し、引き算。39.9-39なので、0.9という答えを期待しますが、実際は、0.899999999999999が返ってきます SyosutenBubun = SyosutenBubun * 10 SyosutenWoKaesu = Fix(SyosutenBubun) '10倍した数の整数部なので、8を返します。困ります。 End Function ------------------------------------- なんで 39.9 - 39 が0.9じゃないんでしょうか? しかも、10.9など、少ない数字だと、きちんと演算されます。また、100.9などだと、途中、0.900000000000006などの数値になるんですけど、答えはきちんと9を出力します。 また、小数点第一位が9以外だと、うまくいくんです。 ちなみに、CDbl関数を使わなくても同じでした。また、-演算子の代わりに、Mod演算子(割り算の余りを返す演算子)を使っても全く同じでした。 なんでこんな不正確な演算結果になるんでしょうか? あるいは、別のもっとスマートな方法がありますでしょうか? よろしくお願い申し上げます。

  • VB6-標準モジュールとの変数の受け渡し

    VB6の初心者です。ごく初歩的な問題でお恥ずかしいのですが困っています。 標準モジュール内にある以下のサブルーチンを行わせるために、 Sub Transform(NumSamples As Long, RealIn() As Double, ImageIn() As Double, RealOut() As Double, ImagOut() As Double, Optional InverseTransform As Boolean = False) (NumSamples、RealIn()、ImageIn()は入力値) (RealOut()、ImagOut()は戻り値) ... ... End Sub フォームモジュール内で以下のようにコールすると、 Private Sub cmdStart_Click() Dim A as Long Dim B(10000) as Double Dim C(10000) as Double Dim D(10000) as Double Dim E(10000) as Double ... (A,B,Cに数値入力) ... Call Transform(A, B(), C(), D(), E(), False) End Sub で実行すると、変数D()に対して「コンパイルエラー:型が一致しません:配列またはユーザ定義型を指定してください」が出ます。なお、配列は10000まで宣言していますが実際には0~4096を使っています。 変数型は合わせているはずなのになぜエラーになるのでしょうか。D(),E()の型宣言をPublicにして標準モジュール内に入れたり、いろいろやってみたつもりですがうまくいきません。 よろしくお願いします。

  • VBA Functionプロシージャで複数の値を

    エクセルでVBAのFunctionプロシージャについて複数の値を戻り値として 受け取る方法を考えています。 下記のようなサンプルプログラムを作りました。 --------------------------------------------------------------------------------- Option Explicit Private Sub CommandButton1_Click() Dim kekka(3) As Double Dim txt As String txt = "12.12A,34.34B,56.56C,78.78D" kekka(0) = test(txt) End Sub Public Function test(ByVal text As String) As Double Dim txt_kakou(3) As String '## 渡された「txt = "12.12A,34.34B,56.56C,78.78D"」を加工し、数値のみを取り出し '## 下記のように配列txt_kakou(3)に振り分ける '## 加工方法は割愛 txt_kakou(0) = 12.12 txt_kakou(1) = 34.34 txt_kakou(2) = 56.56 txt_kakou(3) = 78.78 'string型からdouble型に変換する。 txt_kakou(0) = CDbl(txt_kakou(0)) txt_kakou(1) = CDbl(txt_kakou(1)) txt_kakou(2) = CDbl(txt_kakou(2)) txt_kakou(3) = CDbl(txt_kakou(3)) test = txt_kakou() End Function ----------------------------------------------------------------------------------- まず、呼び出し側のプロシージャでkekka(3)という配列を宣言します。 次に変数txtに「"12.12A,34.34B,56.56C,78.78D"」の文字列を代入します。 そして変数txtをFunctionプロシージャに投げます。 Functionプロシージャでは、受け取った「"12.12A,34.34B,56.56C,78.78D"」 を数値のみに分解し、4つの変数に代入します。 この4つの変数も配列で用意し、txt_kakou(3)とします。 このtxt_kakou(3)を呼び出し元に返し、呼び出しもとの変数kekka(3)に入れたいのです。 また、はじめ変数txtに代入される値は文字列ですが、この文字列をFunctionプロシージャで分解し、 分解した値は、最終的には数値として扱いたいので、途中でdouble型に変換しています。 これを実行すると、Functionプロシージャの最後のtest = txt_kakou()で、型が一致しません といわれてしまいます。 どのように書き直せばいいのでしょうか。 よろしくお願いします。

専門家に質問してみよう