(以下質問)
ニュートン・ラフソン法を用いて根を求めるプログラムについてですが、与えられた式
f(X)=X^2-333=0
で試行値:X0=1,5,10,50,100,500と変えていくとき(*RUN一回のみ)の解が求められないです。試行値を個々に与えて(INPUT6回)求めることはできました。ですが一度に列挙することができません。
私がやってみました方法は
1)試行値を関数(数列化)にしてみる。
2)元々の関数を関数(数列化)にしてみる。
3)IF文もしくはREAD文を用いる。
の3つですが、どの方法を取ってもエラーが止みません><。
基本的なことでしたら申し訳ないのですが、アドバイス、方針、対処策等教えて頂けたら嬉しいです。なお現在までにできているプログラムを書いておきたいと思います。ご参考ください。
(以下プログラム)
120 REM*******ニュートン・ラフソン法*********
130 N=1
140 INPUT"試行値は";X0:
145 PRINT X0
150 ER=.00001
180 FX=X0*X0-333
190 DFX=2*X0
200 X1=X0-FX/DFX
220 IF ABS(X1-X0)<ER THEN 250
230 X0=X1 :N=N+1
240 GOTO 180
250 PRINT X1,N
280 END
120 REM*******ニュートン・ラフソン法*********
130 'N=1
132 read no
140 'INPUT"試行値は";X0:
142 read x0
145 PRINT X0
150 ER=.00001
180 FX=X0*X0-333
190 DFX=2*X0
200 X1=X0-FX/DFX
220 IF ABS(X1-X0)<ER THEN 250</p>
230 X0=X1 :N=N+1
240 GOTO 180
250 PRINT X1,N
255 if n<no then 142</p>
280 END
300 '個数
310 data 6
320 '入力データ
330 data 1,5,10,50,100,500
こんな感じでしょうか。
http://www.netfort.gr.jp/~ohura/b2c/GRAMMAR-jp.html
BASIC はすっかり忘れてしまったので、
おおぼけかましてしまいましたらお詫びします。
INPUT文を使って試行値を入力しなくていいのなら、
という手法が使えるんじゃないでしょうか。
こんな感じです。
120 REM*******ニュートン・ラフソン法********* 123 REM ###試行値を配列に格納 124 DIM X0(0)=1 125 DIM X0(1)=5 126 DIM X0(2)=10 127 DIM X0(3)=50 128 DIM X0(4)=100 129 DIM X0(5)=500 130 N=1 140 REM ###これは無し→ INPUT"試行値は";X0: 142 REM ###FOR NEXT loop 143 FOR I=0 TO 5 145 PRINT X0(I) 150 ER=.00001 180 FX=X0(I)*X0(I)-333 190 DFX=2*X0(I) 200 X1=X0(I)-FX/DFX 220 IF ABS(X1-X0(I))<ER THEN 250 230 X0(I)=X1 :N=N+1 240 GOTO 180 250 PRINT X1,N 260 NEXT I 280 END
BASIC実行環境が無いので走らせていませんが、
大方こんなもんじゃないかと思います。
DIM文でエラーが出ちゃいましたけど次のようにやりましたらできました。
122 DIM X0(6)
124 X0(1)=1
125 X0(2)=5
126 X0(3)=10
127 X0(4)=50
128 X0(5)=100
129 X0(6)=500
DIM文を用いてできました!ご回答有難うございます。
(質問追記)
DIM文を用いることで、できてみて気づいたのですが、収束回数が累計で表示されてまいます。これを個々の解に対応した収束回数で示すにはどうすればよいのでしょうか。以降コメントしてくださる方はこの点について触れていただけますと嬉しいです。
このプログラムではfor文が一度も使われていません.
全部で6回INPUTしたいなら
***************
for i=1 to 6
(質問者さんの書いたプログラム処理内容)
next1 i
***************
というfor文でループをまわしてx0の値を変えてください.
これで6回繰り返されるはずです.
******余談******
以上のものが一番簡単だとおもいますが,これだと,それぞれのX0の値を出力して,次のX0の値を入力したときに,前のX0の値とNの値を廃棄するので,もし全部記憶したままでいたいなら,
x0(i)
n(i)
とかいて,iだけをループでまわせば配列がつくれます.
もしiの値が10を超えるなら
DIM X0(20)
DIM N(20)
などして添字の部分だけループをまわす方法もあります.
http://lcl.web5.jp/prog/basic/
BASICと聞いて懐かしく思いました.
久々にBASICのコードを見れて嬉しかったです.
DIM文を用いて出来ましたー。ご回答有難うございます。
まず、1,5,10,50,100,500 を関数にして見ましょう
プログラム1
10 X0=1 20 FOR I=1 TO 6 30 PRINT X0 40 IF I MOD 2 =1 THEN X0=X0*5 ELSE X0=X0*2 50 NEXT I |
これは、初期値 1 にして、試行回数が奇数の時は次の値に5を、偶数の時には2をかけるものです
次にもともとの関数を関数化してみます
プログラム2
10 N=1 20 INPUT"試行値は";X0: 30 PRINT X0 40 GOSUB *FUNC 50 PRINT X1,N 60 END:'忘れない 200 *FUNC 210 ER=.00001 220 FX=X0*X0-333 230 DFX=2*X0 240 X1=X0-FX/DFX 250 IF ABS(X1-X0)<ER THEN 280</p> 260 X0=X1 :N=N+1 270 GOTO 220 280 RETURN:'関数から戻るとき |
このように、GOSUBで呼び出し、RETURNで戻ります
セットになっていなければエラーになります
また、メインプログラムの後にサブルーチンがある場合は
ENDを忘れるとプログラムがそのままサブルーチンと
くっついてしまうので気をつけます
今度はREADによる読み込みをプログラム2に組み込んでみます
プログラム3
5 FOR I=1 TO 6 10 N=1 20 READ X0: 30 PRINT "試行値は";X0 40 GOSUB *FUNC 50 PRINT X1,N 60 NEXT I 70 END:'忘れない 100 DATA 1,5,10,50,100,500 200 *FUNC 210 ER=.00001 220 FX=X0*X0-333 230 DFX=2*X0 240 X1=X0-FX/DFX 250 IF ABS(X1-X0)<ER THEN 280</p> 260 X0=X1 :N=N+1 270 GOTO 220 280 RETURN:'関数から戻るとき |
DATA文 はプログラムの何処にはいっていても構いませんが
処理するごとに定数を初期化するのを忘れないようにします(ここでは N=1)
これを参考にプログラム1と2を組み合わせたものも
作ることができれば大丈夫だと思います
答えは後日、このページにダイアリからトラックバックします
http://www.vector.co.jp/soft/win95/prog/se055956.html
家で実習するならこちらのプログラムを使うとよいでしょう
RETURN+GOSUBのサブルーチンとFOR~NEXT、READ~DATA文を駆使してできるようになりました。ご丁寧な解説有難うございました。aki73ixさんの方法も後日試したいと思います。
DATA 文を最下行に置く。
それから、配列を利用してFor...Next で作業を繰り返す。
ということでうまくいきます。
このプログラムは333の平方根の近似値を求めるものですから、333の部分をaなどの変数に変えて、aをinput文で入力させるようにすれば、汎用性がアップします。
ちなみに、わたしは Avtive Basic(フリーソフト)がお勧めです。
---------------------------------------------------
10 dim dat(10)
20 for i=1 to 6
30 read dat(i)
40 next
45 ER=0.0001
50 for i=1 to 6
60 X0=dat(i)
130 N=1
180 FX=X0*X0-333
190 DFX=2*X0
200 X1=X0-FX/DFX
220 IF ABS(X1-X0)<ER THEN 250</p>
230 X0=X1 :N=N+1
240 GOTO 150
250 PRINT dat(i),X1,N
260 next
280 END
300 data 1,5,10,50,100,500
ご回答有難うございます。
前回回答の補足です。
data 文の置き場には注意が必要です。
例えば下記のプログラムではエラーを起こします。
繰り返し処理の途中に置くことは避けなければ習いでしょう。
-------------------------------------------------
10 dim dat(3)
20 for i=1 to 3
30 read dat(i)
35 data 1,2,3
40 next
60 for i=1 to 3
70 print dat(i)
80 next
85 goto 20
90 end
補足有難うございます。繰り返し処理ってややこしい。サブルーチン、return、等出て来ますと頭痛くなります><。。
ご回答有難うございます。そのままやるとエラーが出ますが、少し直して頑張ってみます。