• ベストアンサー

10万回でも動くようにするには?

円周率を求めるプログラムを習い自分で入力してみました。以下のものです(質問上不要な部分もあるかもしれませんが、どこまで載せればいいのか分かりませんでしたのでほとんど載せちゃいます) Sub CalcPi() Const NumOfSim = 20000     ____省略_____  Randomize counter = 0 For i = 1 To NumOfSim XRand = Rnd() * 2 - 1# YRand = Rnd() * 2 - 1# Worksheets("sheet1").Cells(i, 5) = XRand Worksheets("sheet1").Cells(i, 6) = YRand distance = (XRand ^ 2 + YRand ^ 2) ^ (0.5) If distance <= 1# Then counter = counter + 1 End If Worksheets("sheet1").Cells(3, 1) = i Next i SimPi = counter / NumOfSim * 4 Worksheets("sheet1").Cells(1, 1) = SimPi End Sub このプログラムの2万回を10万回にしたらエラーメッセージが出て「オーバーフロー」となりました。 そこでお聞きしたいのですが、 (1)10万回でもエラーが出ないようにするにはどのような命令を追加すればいいのでしょうか? (2)エラーが出るのはNumOfSimに確保されているメモリーの容量(表現が正しいか分かりません)が足りないからなんでしょうか? なにぶんど初心者で(2)は噛んで含めるようにお願いいたします。

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

  • ベストアンサー
回答No.7

Integer型変数は16bitの箱、Long型変数は32bitの箱を用意するという考え方でよいと思いますよ。 以下はOption Explicitについてです。 Option explicitを挿入しておくと、宣言していない変数をプログラムで使用していた場合にエラーが発生します。 質問者の方は、実際にはiを宣言していたようですが、Option explicitがない場合は、宣言無しにiを使っていてもエラーが発生しません。 自動的にiはVariant型として処理されます。 宣言無しに変数を使えるのは、一見便利に見えますが、プログラムの規模が大きくなってくると厳密に変数を管理する必要が出てくるため、変数は型も明確にして宣言する必要が出てきます。 また、使用メモリを必要最小限に抑えるためにも、厳密な型宣言が必要になってきます。 No.6の方が仰っている設定をすれば、“設定後に新たに作られるモジュールには”自動的に先頭にOption Explicitが入ります。 しかし、既に生成済みのモジュール(例えばCalcPi()が含まれるモジュール)には、設定を変更しても自動的にOption Explicitが挿入されませんので、自分で入れてやる必要があります。

bataiu
質問者

お礼

何度も回答していただきありがとうございました。非常に分かりやすくよく理解できました。お世話になりました。

その他の回答 (7)

  • hssh
  • ベストアンサー率24% (12/49)
回答No.8

No1 hsshです もしかして、先のアドバイスは間違っていたかもしれません 宣言しない変数はvariantなんですね てっきりintegerだと思っていました(昔のCと勘違い) どうやらエラー原因は、エクセルそのものの仕様にあるようです お使いのエクセルの仕様を確認してください たぶん、65,536行までしか使えないはずです というわけで、エラーを出さない為には、行数制限内で表示するように工夫しましょう どちらにせよ、皆さんのいわれるように変数宣言はしたほうが良いですよ 私も、まだまだ未熟者でした (^ ^;;

bataiu
質問者

お礼

ご親切にありがとうございました。そうなんです、10万回やるときは行が足りずにエラーになるので、毎回結果を表示する命令を外しました。

回答No.6

VBAのツール - オプションで「変数の宣言を強制する」にチェックを入れておくと自動でOption Explicitを入れてくれるので、チェックしておいた方がよいです。 参考:バグの少ないプログラム http://www.gld.mmtr.or.jp/~kunosk/home/excel/excel1.htm

参考URL:
http://www.gld.mmtr.or.jp/~kunosk/home/excel/excel1.htm
bataiu
質問者

お礼

回答ありがとうございました。事前にそのように設定できるんですね。参考URLもありがとうございました。

  • imogasi
  • ベストアンサー率27% (4737/17070)
回答No.5

計算機の「1」変数の保持できる数の桁数や文字の長さには、必ず制限があります。また配列の要素数もメモリ容量との関連で制約があります。そのことを、繰り返し計算するときはまず念頭に置かねばなりません。 そのほかに、 >「円周率を求めるプログラム」とありますが、本質問は モンテカルロ法による、円周率計算法と言います。 質問の表題としては、そのことを明記すべきでは無いかと 思います。 学理的には、少し重要でも、円周率の求め方としてはなかなか収束が悪い方法です。 http://www.cc.toin.ac.jp/club/cl01/program/pi.html 他「モンテカルロ法 円周率」でWEB照会すると数百件出てきます。 本当の円周率の多桁計算は、アルゴリズムである○○法(マーチンの公式など)の勉強が必要です。 http://www.pluto.ai.kyutech.ac.jp/plt/matumoto/pi_small/node42.html それと、計算途中で上位桁から確定桁が確定すると、ディスクに書き出し、メモリ上の数字としては全部は記憶しません。そのためのアルゴリズムの勉強が必要です。 数学が得意でない方には結構難しいと思います。 こちらも円周率の計算やパイ(π)でWEB照会すれば数百件出てきますので雑学的知識を得るには困りません。

bataiu
質問者

お礼

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

回答No.4

エラーがでる直接の原因は、   Const NumOfSim = 20000   ↑NumOfSimの型が宣言されていない または、   For i = 1 To NumOfSim   ↑iが明確に宣言されていない のどちらか、あるいは両方だと思います。 質問(1)の回答: NumOfSimを100,000にしてもエラーが出ないようにするためには、   Const NumOfSim As Long = 100000 のようにNumOfSimを明確にLong型で宣言し、   Dim i As Long をFor文の前に挿入すればよいと思います。 質問(2)の回答: 回答の前にまず気になるのは、明示的に型を宣言しなかった場合はVariant型(なんでもあり)とみなされ、オーバーフローは発生しないはずです。 ExcelのVBAのようですので、Excelのバージョンなどにもよるのかもしれませんね。 オーバーフローが発生している以上、NumOfSimかiがInteger型として認識されているのだと思います。 以下、質問者の方の環境では、特に型を宣言しなかった場合はInteger型とみなされると仮定しての回答です。 ExcelのVBAのヘルプによると、Integer型は、-32,768~32,767の範囲の値をとることができます。 NumOfSimがIntegerであったとしても、20,000であれば格納できますし、それを代入するiがIntegerであったとしても20,000なら代入できます。 32,767よりも大きい値である100,000を格納するためには、Long型として変数を宣言する必要があります。 Long型であれば、-2,147,483,648~2,147,483,647の範囲の値をとることができます。 変数を利用するときには、面倒でも必ず型を明確に宣言したほうが良いでしょう。 また、変数の宣言を強制するOption Explicit文も入れたほうが良いでしょう。

bataiu
質問者

お礼

細かく回答していただきありがとうございました。ずっと昔にBASICをやったことがあるのですが、VBAは初めてで分からないことがまだまだ多い状況です。どうもお世話になりました。

bataiu
質問者

補足

実は必要ないと思いまして省略した部分にDim i As Integer という一文がありました。これをご指摘の通りLongにしましたらうまくいきました。すみませんでした。 ところで、Integerは32,768+32,767=65,535 Longは足して4,294,967,295でそれぞれ2の16乗と32乗となると思います。ということはIntegerはNumOfSim用に16ビットのデータを収める箱を、LongはNumOfSim用に32ビットの箱を用意してください、という命令と考えればよろしいのでしょうか? あと最後のOption Explicit文は入れないと何か不都合が出てくるのでしょうか?

  • adan99
  • ベストアンサー率0% (0/1)
回答No.3

For I <- Iを Long等に宣言してみてはいかがでしょうか?

bataiu
質問者

お礼

回答どうもありがとうございました。どうも、ご指摘の通りだったようです。

  • hssh
  • ベストアンサー率24% (12/49)
回答No.2

No1 hsshです。文面を改めて読んでみて、質問者の方は、もしかして原因はわかっているのかもしれないので補足します > 10万回でもエラーが出ないようにするにはどのような命令を追加すればいいのでしょうか? 変数宣言を入れましょう あと、インデントもあったほうがバグが減ります

bataiu
質問者

お礼

ありがとうございました。インデントは初めて聞きました。

  • hssh
  • ベストアンサー率24% (12/49)
回答No.1

VBではなく、エクセルのVBAのようですね プログラミングの力とは、問題解決をする力なのだが どういう原因究明方法をとりましたか? 原因はとっても簡単な事ですよ まず、プログラムを極限まで簡単にして、 そこから、少しづつ機能を増やしていきましょう たとえば、なにもしないカウンタupだけとか (ほとんど答えだけどね)

bataiu
質問者

お礼

ありがとうございました。VBAは始めて数日で、原因究明方法も思い浮かびませんでした。

関連するQ&A