プロが教えるわが家の防犯対策術!

VBAを使って4バイトを10進数に変換する方法に関してですが


Dim aaa(3) As Byte
Dim bbb As Long

aaa(0) = 7
aaa(1) = 15
aaa(2) = 15
aaa(3) = 15


bbb = aaa(0) * 4096 + aaa(1) * 256 + aaa(2) * 16 + aaa(3)

bbb = (CInt(aaa(3))) Or (CInt(aaa(2)) * &H10&) Or (CInt(aaa(1)) * &H100) Or (CInt(aaa(0)) * &H1000)

上記の二つの方法が上げられます。
速度を比較したところ、
一つ目の方法の方が30%程度高速であることが分かりました。
それで一つ目の方法を使いたいのですが、
aaa(0)が7以下(bbbが32767以下)なら問題ないのですが
aaa(0)が8以上(bbbが32768以上)になるとなぜかオーバーフローしてしまいます。

32767上限というとintegerの上限のはずですが、
aaa(0)をintegerで定義しても同じところでオーバーフローしてしまいます。
aaa(0)をlongで定義するとオーバーフローしなくなります。

掛け算するときに、入力変数の上限が出力結果に影響を及ぼすのはなぜなのでしょうか?
一度、aaa(0) * 4096の結果が、aaa(0)に代入されてから
bbbに代入されているのでしょうか?

もしそうだとしてもbyteでの上限が255にならず
32767になるのはなぜなのでしょうか?

質問者からの補足コメント

  • ありがとうございます。

    あと、
    dim bbb as double
    aaa(0) = 255
    aaa(1) = 85
    aaa(2) = 85
    aaa(3) = 85

    bbb = CDbl(aaa(0)) * 16777216 + (aaa(1)) * 65536 + (aaa(2)) * 256 + aaa(3)
    これはオーバーフローしなかったのですが
    bbb= (aaa(3)) Or (aaa(2) * &H100&) Or (CDbl(aaa(1)) * &H10000) Or (CDbl(aaa(0)) * &H1000000)

    これがオーバーフローするのはなぜでしょうか?

    No.3の回答に寄せられた補足コメントです。 補足日時:2015/10/29 13:52
  • たびたび、すいません、

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

    No.5の回答に寄せられた補足コメントです。 補足日時:2015/10/29 20:16

A 回答 (5件)

> bbb= (aaa(3)) Or (aaa(2) * &H100&) Or (CDbl(aaa(1)) * &H10000) Or (CDbl(aaa(0)) * &H1000000)


> これがオーバーフローするのはなぜでしょうか?

私の環境では、以下の様になりました。
2147483647 Or 1 → 2147483647
2147483648 Or 1 → オーバーフロー

ビット演算を行う場合は両側の数値をInteger型に変換して演算を行う様です。
従ってInteger型の表現できる範囲を超えた数値はオーバーフローします。


※これまでの流れでOr演算子が登場する意図がわかりません。
 行いたい目的を記載されたほうが、より適切な回答が付くのではないでしょうか?
この回答への補足あり
    • good
    • 0

URURURUU様



VBは計算する時、右辺のそれぞれの数値の型をみて最大の値が入る型を決定します。
下記を見ますと、右辺は Byte型と整数定数なので【整数型】と判断しています。
よってどれか一つでも大きな数値型を使用すれば良いです。
※例は4096を長整数型(Long)にしています。

bbb = aaa(0) * 4096& + aaa(1) * 256 + aaa(2) * 16 + aaa(3)

お試し下さい。
    • good
    • 0

bbbは代入先としてLong型であると定義しているだけであって、


計算式じたいがLongとは一言もいっていません。

aaa(0) * 4096
という数式を見た場合、Byte型とInteger型です。
この式を処理した時、より表現力の高いInteger型として処理されます。

にも関わらず、Integer型より大きい数値が求められてしまったがためのエラーでしょう。

つまり、解消するには、
bbb = CLng(aaa(0)) * 4096 + CLng(aaa(1)) * 256 + CLng(aaa(2)) * 16 + CLng(aaa(3))
もしくは
bbb = aaa(0) * CLng(4096) + aaa(1) * CLng(256) + aaa(2) * CLng(16) + aaa(3)
とする必要があります。
この回答への補足あり
    • good
    • 0

Byte型は(計算)式がShort型に変換される仕様。


だから、計算結果が -32,768 から 32,767 の範囲に入らない場合にオーバーフローします。
    • good
    • 0

VBA の変換規則は知らんが, どうせ


・結果の型はオペランドの型で決まる
・2つのオペランドの型が違っている場合には「大きい」方の型にそろえられる
くらいじゃないかねぇ.
    • good
    • 0

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