![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
円周率を求めるプログラムを習い自分で入力してみました。以下のものです(質問上不要な部分もあるかもしれませんが、どこまで載せればいいのか分かりませんでしたのでほとんど載せちゃいます)
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が挿入されませんので、自分で入れてやる必要があります。
No.8
- 回答日時:
No1 hsshです
もしかして、先のアドバイスは間違っていたかもしれません
宣言しない変数はvariantなんですね
てっきりintegerだと思っていました(昔のCと勘違い)
どうやらエラー原因は、エクセルそのものの仕様にあるようです
お使いのエクセルの仕様を確認してください
たぶん、65,536行までしか使えないはずです
というわけで、エラーを出さない為には、行数制限内で表示するように工夫しましょう
どちらにせよ、皆さんのいわれるように変数宣言はしたほうが良いですよ
私も、まだまだ未熟者でした (^ ^;;
ご親切にありがとうございました。そうなんです、10万回やるときは行が足りずにエラーになるので、毎回結果を表示する命令を外しました。
No.6
- 回答日時:
VBAのツール - オプションで「変数の宣言を強制する」にチェックを入れておくと自動でOption Explicitを入れてくれるので、チェックしておいた方がよいです。
参考:バグの少ないプログラム
http://www.gld.mmtr.or.jp/~kunosk/home/excel/exc …
参考URL:http://www.gld.mmtr.or.jp/~kunosk/home/excel/exc …
No.5
- 回答日時:
計算機の「1」変数の保持できる数の桁数や文字の長さには、必ず制限があります。
また配列の要素数もメモリ容量との関連で制約があります。そのことを、繰り返し計算するときはまず念頭に置かねばなりません。そのほかに、
>「円周率を求めるプログラム」とありますが、本質問は
モンテカルロ法による、円周率計算法と言います。
質問の表題としては、そのことを明記すべきでは無いかと
思います。
学理的には、少し重要でも、円周率の求め方としてはなかなか収束が悪い方法です。
http://www.cc.toin.ac.jp/club/cl01/program/pi.html
他「モンテカルロ法 円周率」でWEB照会すると数百件出てきます。
本当の円周率の多桁計算は、アルゴリズムである○○法(マーチンの公式など)の勉強が必要です。
http://www.pluto.ai.kyutech.ac.jp/plt/matumoto/p …
それと、計算途中で上位桁から確定桁が確定すると、ディスクに書き出し、メモリ上の数字としては全部は記憶しません。そのためのアルゴリズムの勉強が必要です。
数学が得意でない方には結構難しいと思います。
こちらも円周率の計算やパイ(π)でWEB照会すれば数百件出てきますので雑学的知識を得るには困りません。
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文も入れたほうが良いでしょう。
この回答への補足
実は必要ないと思いまして省略した部分に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文は入れないと何か不都合が出てくるのでしょうか?
細かく回答していただきありがとうございました。ずっと昔にBASICをやったことがあるのですが、VBAは初めてで分からないことがまだまだ多い状況です。どうもお世話になりました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) なぜExit Subがあるのかわかりません 4 2023/02/19 12:34
- Visual Basic(VBA) VBAコードが作動せず、どこに問題があるのか教えて下さい。 3 2023/06/13 13:20
- Excel(エクセル) VBAの指示の内容 昨日こちらでご教示頂いたのですが初心者な為、一つ一つの指示が何をやっているのかわ 2 2022/10/25 18:08
- Visual Basic(VBA) VBA処理追加 こちらでご教示頂いたのですが回答完了させてしまいましたのでこちらからまた質問させてく 2 2022/10/27 09:57
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
- Excel(エクセル) VBAのエラーが直せません 4 2023/06/12 22:10
- Visual Basic(VBA) 前回ご教授いただいたコードに覚えたてのループ処理で品名りんごAから順に20回for nextでループ 7 2023/01/13 22:01
- Visual Basic(VBA) vbaを早くしたい 5 2022/09/09 10:58
- Visual Basic(VBA) ユーザーフォーム「frm_基本❶」を立ち上げると新規で入力する行数を右下のNoとして表示しています。 1 2023/03/16 19:02
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
10万回でも動くようにするには?
-
エクセルVBA 宣言Dimの場所
-
TCPサーバ bind関数のエラーに...
-
VBSでIEを起動し、拡大率を変更...
-
ソケット通信で同時受信の制限?
-
ASP.netで使用するWEBサーバに...
-
Access vbaに関して
-
ページの更新内容が反映されない。
-
IIS7.5の設定の仕方
-
GridView表示の高速化
-
C# try-catch でcatchに飛ばす方法
-
VBSからPDFファイルを開きたい...
-
画面のリフレッシュを意図的に...
-
CreateObject("Excel.Applicati...
-
ADSIについて
-
Response.Redirectで引数2つの...
-
SqlDataSource SelectCommand ...
-
ASP.NETで使用しているJavascri...
-
VBA RemoveDuplicatesで「アプ...
-
C# のプログラミングについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルVBA 宣言Dimの場所
-
ソケット通信で同時受信の制限?
-
vbscriptの変数宣言
-
名前が二重に定義されています
-
EXCEL VBA API宣言でコンパイル...
-
VBSでIEを起動し、拡大率を変更...
-
VBSにてサーバー中のエクセルフ...
-
式はメソッドではありませんと...
-
ハンゲーム
-
COBOLのPERFORM文
-
標準モジュールPublic宣言変数...
-
golang 空文字判定について
-
TCPサーバ bind関数のエラーに...
-
ACCESSのAutoKeysマクロでアク...
-
CreateObjectの同時実行時について
-
十進BASICについて
-
ダブルクォーテーションの吐き出し
-
エクセル同一セル内の指定文字...
-
イメージ表示
-
C# try-catch でcatchに飛ばす方法
おすすめ情報