VBエラーのオーバーフロー

解決


とっしー  2007-07-05 21:11:18  No: 136914

お世話になります。使用環境はWinXP(SP2)+VB6(SP6)です。

質問はVBエラーのひとつの”オーバーフローしました。(Error 6)”に関してです。
例えば、VBヘルプにも記載されている↓

    Dim x As Long
    x = 2000 * 365   ' エラー: 値がオーバーフローします。

このようなエラーでは、次のように対処してください。

    Dim x As Long
    x = CLng(2000) * 365

というものなんですが、この点で下記の2点が分かりません。

①変数xはLong型の32 ビット(-2,147,483,648 〜 2,147,483,647) の範囲の値をとれるのに、
代入値(2000*365=730,000)がなぜ代入・計算ができないのか。

②VBヘルプでは”CLng関数を使用して対処”してくれということですが、
どのくらいCLng関数を付加して対処すればいいのかという基準が分からない。

過去ログ・VBヘルプ・ネットで調べていましたがいまいち理解できませんでした。
よろしくお願いします。


Hongliang  URL  2007-07-05 21:39:25  No: 136915

VB6 まででは、数値は暗黙的に Short として理解されます。
当然、リテラル(コードにベタ書きした数値)もそうですから、2000 と 365 はどちらも Short です、
同じ型同士の演算結果は同じ型で返されます。Short 同士である 2000 と 365 の積も Short として返そうとします。
当然、オーバーフローです。
演算結果の格納先が Long じゃないか、と言う疑問があると思いますが、手順としてまず演算を行い、その結果を変数に代入するわけで、この場合一歩目でこけているので二歩目に意味はありません。

> どのくらいCLng関数を付加して対処すればいいのか
Short の範囲内では収まらなさそうな箇所についてです。第三者には判断できません。


KG  2007-07-05 21:43:14  No: 136916

演算する値がIntegerの範囲だと結果もIntegerになるみたいです。

Integer * IntegerだとInteger
Long * IntegerだとLong

が帰ってくるみたいですね。

MSDNにそれらしきものが載っていたので参考までに
http://msdn2.microsoft.com/ja-jp/library/ms235255(VS.80).aspx

#みるとこ間違ってないことを祈ります|o_o;


KG  2007-07-05 21:43:59  No: 136917

うおお、色々調べてたらHongliangさんがピシャリ orz


Hongliang  URL  2007-07-05 21:47:42  No: 136918

しかし VB6 では Short ではなく Integer でしたね orz
私の投稿の Short は全て Integer と読み替えてください。


魔界の仮面弁士  2007-07-05 22:08:53  No: 136919

型宣言文字として、
  「%」→Integer
  「&」→Long
  「@」→Currency
  「!」→Single
  「#」→Double
  「$」→String
などが用意されているので、これらを使うのも有効です。

たとえば、CLng 関数を使った
>> x = CLng(2000) * 365
という式を、
  x = 2000& * 365&
のようにしても、Long型の精度で演算されます。

ちなみに、
  MsgBox TypeName(2000)
  MsgBox TypeName(2000&)
  MsgBox TypeName(2000& * 365&)
などとすれば、データ型をチェックできます。

> どのくらいCLng関数を付加して対処すればいいのかという基準が分からない。
「演算の精度」で判断することになりますが、整数同士の加減算程度なら、
よほど大きい数でない限り、大抵は Long で大丈夫でしょう。

注意するべきは、「除算演算」が含まれる場合ですね。
値が浮動小数になりやすいため、金額計算などにおいては演算誤差や丸め誤差に注意が必要です。


とっしー  2007-07-05 22:52:27  No: 136920

Hongliangさん、KGさん、魔界の仮面弁士さんありがとうございます。
つまり”x=2000*365”という式には

”計算結果(変数へ代入する前の値)としての型”
”代入先の変数の型”

の2種類が存在しているということですね。
また、下記のように理解しました。

①////////////////////
x=2000*365

演算型×(Integer型のオーバーフロー)
代入型○
//////////////////////

②////////////////////
x=2000&*365&

演算型○
代入型○
//////////////////////

あと、魔界の仮面弁士さんが書いてくれた
TypeNameという便利な関数は今後使っていきたいと思います。

みなさんの早レスで次へ進めそうです。
本当にありがとうございました!


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

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






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