• 締切済み

vbaで、連立方程式を解く方法について

掃き出し法を使って解くようですが、 -1 0 0 2 0 0 0 0 0 -1 -2 0 0 0 0 -2 0 0 -1 1 0 0 2 1 0 0 0 0 0 0 0 -2 0 -1 0 0 0 0 2 0 0 1 このように、行の入れ替えが必要な場合、繰り返しを用いて行を入れ替える必要がありますよね? 下のように作ってみましたが、上手くいきません。↑の行列を正しく入れ替えるだけならできるのですが、もう一度プログラムを作動させるとエラーが出ます。 For j = l To 6 If Abs(a(j, l)) >= Abs(max) Then'0と負の値しかない場合、0が最大になってしまう u = j 'このときの行を保存 End If Next j For m = 1 To 7 brank = a(l, m) '入れ替える前の値を保存 a(l, m) = a(u, m) a(u, m) = brank Cells(l, m) = Cells(u, m) Cells(u, m) = brank Next m Next l do loopを使った方が良いと聞いたのですが、どのようにすればよいのでしょうか?

みんなの回答

  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.3

#1です。 プログラムを見ましたが、掃き出し法のアルゴリズムが間違ってます。 プログラムを見ると、 まず、行の入れ替えで対角上に最大の数値を移してから、そのあとに掃き出し法の計算で対角以外を0にしていますね。 この方法では、行の入れ替えで必ずしも対角上に0以外の数値がくるとは限りません。 実際、2回目の実行では、行の入れ替えをしてもCells(5,5)が0になっています。 これがエラーになる原因です。 正しい掃き出し法のアルゴリズムは、 行の入れ替えと行の計算を別々に行うのではなく、同じループの中で行います。 For n = 1 to 6  (n列n行が最大数値になるようn+1行以降の行と入れ替える)  (n列のn行を1に、n行以外が0になるように計算する) Next n

全文を見る
すると、全ての回答が全文表示されます。
  • layy
  • ベストアンサー率23% (292/1222)
回答No.2

アルゴリズムを確認。サンプルも多数ある。 無駄なループはしてないか、判定なく入れ替えか、初期値は良いか、そんなところから。 1のときどう?、2のときどう?、トレース作業をすると見えてくる。 聞く前にもう一度見る。

全文を見る
すると、全ての回答が全文表示されます。
  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.1

プログラムの一部だけ示されても、エラーの原因を特定するのは困難ですが、あえて想像するなら、 For j = l To 6 If Abs(a(j, l)) >= Abs(max) Then'0と負の値しかない場合、0が最大になってしまう u = j 'このときの行を保存 End If Next j のところで、maxには何の値が入っているんでしょうか? If文がすべてFLASEで、u = j が1回も実行されないとき、uには何の値が入っているんでしょうか? もし、u = 0 なら Cells(l, m) = Cells(u, m) の箇所でエラーになります。 For m = 1 To 7 ・・・・・ Next m で列を入れ替えていますが、入れ替えするかどうかの判定が必要ではないですか? do loopを使った方が良いかどうかは、全体の流れがわからないので何とも言えないです。

WhiteRay
質問者

補足

Sub kadai2() ' 列の入れ替えを行う必要がある Dim a(6, 7) As Double Dim b(6) As Double Dim max As Double Dim f As Single Dim j As Integer Dim i As Integer Dim l As Integer Dim m As Integer Dim n As Integer Dim u As Integer Dim w As Double Dim brank As Double For j = 1 To 6 For i = 1 To 7 a(j, i) = Cells(j, i) Next i b(j) = Cells(j, 7) Next j For l = 1 To 6 i = 1 max = 0 brank = 0 For j = l To 6 '入れ替えの時、iの値が変化していない、繰り返し If Abs(a(j, l)) >= Abs(max) Then max = a(j, l) '行の最大値が分かればよい,最大値を記録する必要無 u = j 'このときの行を保存 End If Next j '繰り返し終わり For m = 1 To 7 brank = a(l, m) '入れ替える前の値を保存 a(l, m) = a(u, m) a(u, m) = brank Cells(l, m) = Cells(u, m) '入れ替えは繰り返し終わった後 lの値が変化しないorz⇒入れ替えてるのはセルだけで、配列を入れ替えていない! Cells(u, m) = brank '入れ替えは繰り返し終わった後 Next m Next l For j = 1 To 6 For i = 1 To 6 a(j, i) = Cells(j, i) Next i b(j) = Cells(j, 7) Next j For j = 1 To 6 For i = 1 To 6 If j <> i Then a(j, i) = a(j, i) / a(j, j) End If Next i b(j) = b(j) / a(j, j) a(j, j) = 1 Cells(j + 7, j) = a(j, j) For l = 1 To 6 If l <> j Then w = a(l, j) For i = 1 To 6 'j列同士の引き算 a(l, i) = a(l, i) - a(j, i) * w Next i b(l) = b(l) - b(j) * w 'wの値がおかしい ここi で繰り返す意味ない。ここでbの値が全く変化していない!A.a(j,7)は存在しない: l =2のとき、b(1)が計算されない End If Next l Next j For j = 1 To 6 For i = 1 To 6 Cells(j + 7, i) = a(j, i) Cells(j + 7, 7) = b(j) Next i Next j End Sub

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • VB2010での連立方程式の計算

    VB2010でガウスの消去法のプログラムを作りたいんですが、うまく解が求まらないのでメールしました。今回の例は未知数8です。ちなみにVBは初心者です。 Myarrayは、列の1-8個目までが、各未知数の係数、9個目が整数を表しています。 行は式を表していて、未知数が8個あるので8行あります。 Dim MyArray(,) As Double = {{-1, 1, -1, 1, 0, 0, 0, 0, 1}, {0, 0, 0, 1, 0, 0, 0, 0, -1}, {0, 0, 0, 0, 0, 0, 0, 1, -1}, {0, 0, 0, 0, 1, 1, 1, 1, 0}, {0, 0, 1, 0, 0, 0, -1, 0, 0}, {0, 2, 0, 0, 0, -2, 0, 0, 0}, {-6, 2, 0, 0, 0, 0, 0, 0, 0}, {6, 2, 0, 0, 0, 0, 0, 0, 0} } Const N = 8 Dim i, j, k, l, pivot As Integer Dim x(N) As Double Dim p, q, m As Double Dim b(1, N + 1) As Double For i = 0 To N - 1 Step 1 m = 0 pivot = i For l = i To N - 1 Step 1 'i列の中で一番値が大きい列を選ぶ If System.Math.Abs(MyArray(l, i)) > m Then m = System.Math.Abs(MyArray(l, i)) pivot = l End If Next 'pivotがiと違えば、行の入れ替え If pivot <> i Then For j = 0 To 8 Step 1 b(0, j) = MyArray(i, j) MyArray(i, j) = MyArray(pivot, j) Myarray(pivot, j) = b(0, j) Next End If Next For k = 0 To N - 1 Step 1 p = Myarray(k, k) '対格要素を保存 MsgBox(p) MyArray(k, k) = 1 '対格要素は1になることが分かっているので代入 For j = k + 1 To N Step 1 MyArray(k, j) = MyArray(k, j) / p Next For i = k + 1 To N - 1 Step 1 q = MyArray(i, k) For j = k + 1 To N Step 1 MyArray(i, j) = MyArray(i, j) - q * MyArray(k, j) Next '0となることが分かってるので代入 MyArray(i, k) = 0 Next Next '解の計算 For i = N - 1 To 0 Step -1 x(i) = MyArray(i, N) For j = N - 1 To i + 1 Step -1 x(i) = x(i) - MyArray(i, j) * x(j) Next Next MsgBox(x(0)) MsgBox(x(1)) MsgBox(x(2)) MsgBox(x(3)) MsgBox(x(4)) MsgBox(x(5)) MsgBox(x(6)) MsgBox(x(7)) 出力結果としてNAN(非数値)と出てきてしまいます。原因は、pに0が入ってしまっていることがあるからだと思いますが、これを回避する方法はないでしょうか?ご教授よろしくお願いします。

  • EXCEL VBAのFor...Nextについて

    VBA初心者です。よく理解していませんので、質問も的を得ていないかもしれませんが、ご指導宜しくお願いいたします。  現在、For...Nextを使った表計算をしています。 A列に「す」という文字が含まれていたら、B列の「す」の行に「あ」と「い」と「え」「か」のセルの合計をだす。C列、D列・・・最終列まで計算する。 上記VBAを作成する方法を教えて下さい。 A  B  C  D  E   F  G  H  I  J  K  L 1 2    3    4   5    6    7    8    9    10    11 12 あ  1 2 3 4   5 6 7 8 9 10 11 い 10 20 30 40  50 60 70 80 90 100 110 う 20 30 40 50   60 70 80 90 100 110 120 え 40 50   60  70 80 90  10 20 120 130 30 お 50 60   70  80 90 10  20 30 130 140 40 か 60 70   80  90 10 20  30 40 140 150 50 す 私は表に1~12まで数字をインプットし下記のようなコードを考えました。 Sub 列合計() Dim i, k, l, m, n As Long j = 2 For i = 6 To 120 For k = 6 To 120 For l = 6 To 120 For m = 6 To 120 For n = 6 To 120 If Cells(i, 1) = "す" And Cells(k, 1) = "あ" And Cells(l, 1) = "い" And Cells(m, 1) = "え" And Cells(n, 1) = "か" Then Do While j <= Range("A2").End(xlToRight) Cells(i, j) = Cells(k, j) + Cells(l, j) + Cells(m, j) + Cells(n, j) j = j + 1 Loop Else: End If Next n Next m Next l Next k Next i End Sub この内容だとエラーが出てしまいます。 補足ですが、あいうえおかの順番はかわったり、間に他の行が入ったりします。 また今回はL列の間としましたが、もっと列が増え、最終列まで計算する方法を知りたいのですが、どうぞ宜しくお願い致します。 ※ofice2013です。

  • VBAで行列を作る方法

    次のようなプログラミングで1,0,-1の要素で作られる3×3行列を全通り調べています。 この場合3の9乗通り調べることができます。 これを4×4や5×5行列など数を大きくして調べたいのですが、このプログラムを配列を使うなどして 簡単にできる方法を教えてください。 よろしくおねがいします。 Sub test() Dim a As Integer '行 Dim b As Integer '列 Dim c As Integer, i As Integer, j As Integer, d As Integer, e As Integer Dim 内積 As Integer, step As Integer Dim f As Integer, g As Integer, h As Integer, l As Integer, m As Integer, n As Integer, k As Integer, x As Integer Dim sum As Integer, total As Integer Dim aa As Integer, aaa As Integer, aaaa As Integer, bb As Integer, bbb As Integer, bbbb As Integer a = 3 '行 b = 3 '列 c = 0 内積 = 0 con = 0 sum = 0 tatal = 0 aa = 0 aaa = 0 aaaa = 0 bb = 0 bbb = 0 bbbb = 0 x = 0 For n = 0 To 2 For m = 0 To 2 For l = 0 To 2 For k = 0 To 2 For h = 0 To 2 For g = 0 To 2 For f = 0 To 2 For e = 0 To 2 For d = 0 To 2 '要素がすべて1 For i = 1 To a For j = 1 To b Cells(i, j) = 1 Next j Next i If bbbb = 1 Then Cells(a - 2, b - 2) = 0 ElseIf bbbb = 2 Then Cells(a - 2, b - 2) = -1 End If If bbb = 1 Then Cells(a - 1, b - 2) = 0 ElseIf bbb = 2 Then Cells(a - 1, b - 2) = -1 End If If bb = 1 Then Cells(a, b - 2) = 0 ElseIf bb = 2 Then Cells(a, b - 2) = -1 End If If aaaa = 1 Then Cells(a - 2, b - 1) = 0 ElseIf aaaa = 2 Then Cells(a - 2, b - 1) = -1 End If If aaa = 1 Then Cells(a - 1, b - 1) = 0 ElseIf aaa = 2 Then Cells(a - 1, b - 1) = -1 End If If aa = 1 Then Cells(a, b - 1) = 0 ElseIf aa = 2 Then Cells(a, b - 1) = -1 End If If total = 1 Then Cells(a - 2, b) = 0 ElseIf total = 2 Then Cells(a - 2, b) = -1 End If If sum = 1 Then Cells(a - 1, b) = 0 ElseIf sum = 2 Then Cells(a - 1, b) = -1 End If If con = 1 Then Cells(a, b) = 0 ElseIf con = 2 Then Cells(a, b) = -1 End If con = con + 1 Next d con = 0 sum = sum + 1 Next e sum = 0 total = total + 1 Next f total = 0 aa = aa + 1 Next g aa= 0 aaa = aaa + 1 Next h aaa = 0 aaaa = aaaa + 1 Next k aaaa = 0 bb = bb + 1 Next l bb = 0 bbb = bbb + 1 Next m bbb = 0 bbbb = bbbb + 1 Next n End Sub

  • VBA For~Next 

    「wsData」の値を「wsInv」の指定セル(=●●●=16)から4つおきに処理したい。 01:Cells(16 + i * 4, 1) とすると「i」が大きいときに   「""」があると16からスタートしない 02:「For k = 0 To 50」を作成したが、何処に入れても上手く処理出来ない。 For i = 0 To 50 '行 For j = 6 To 28 '列 If wsData.Cells(10 + i, 3).Value = "" Then wsInv.Cells(●●●, 1).Value = wsData.Cells(10 + i, 1).Value wsInv.Cells(●●●, j - 2).Value = wsData.Cells(10 + i, 23 + j).Value End If Next j Next i お力添えをお願いいたします。

  • VLOOKUP関数と同じことをVBAでおこなうには

     初めまして、当方VBAの素人です。よろしくお願いします。  同じような質問で、このようなVBAを見つけました。 Sub Macro1() For n = 2 To 5 '処理するSheet2の行数範囲 a = Sheets("Sheet2").Cells(n, 1) 'aにA列の値を代入 For m = 2 To 5 '検索するSheet1の行数範囲 If Sheets("Sheet1").Cells(m, 1) = a Then 'Sheet2のA列の値とSheet1のA列が一致した場合 v = Sheets("Sheet1").Cells(m, 2) 'vにB列の値を代入 Sheets("Sheet2").Cells(n, 2).Value = v 'Sheet2のB列に値を入力 Exit For '値が見つかったのでForを終了 End If Next Next End Sub このVBAではSheet2での検索、入力が列になるのですが、列でなく、行でできないでしょうか。できればSheet1のB列の値をSheet2の1行で検索、Sheet2の2行に入力されるだけではなく、Sheet1のC列の値をSheet3の1行で検索、Sheet3の2行に入力されるようにしたいと思います。  解る方、よろしくお願いします。

  • VBA ファイルの内容を並べ替えたい

    csvファイルを別のファイル(エクセル)に並べ替えて保存したいと考えてVBAでプログラムを 書いてみたのですがうまくできないので解決策をご教示いただけないでしょうか。 960行640列のデータを,「行,列,値」←エクセルでいうとA列=行,B列=列,C列=値 の形に並べ替えようとしています。  行  列  値  1   1   28 1   2  10  1   3   0  ・   ・   ・  ・   ・   ・  960 640  37 といった具合です。 実行すると,行と列は並べ替えて表示されるのですが,値だけはどの行でも同じ値が入ってしまいます。元のデータでは値はランダムです。 書いたプログラムを下に載せます。 配列tmpのインデックスがループを追うごとに変化しないことが原因かと考えていますが, 変数nを追加して ”For tmp = 0 To UBound(tmp) Next n” を ”For j = 1 To 640 Next j” の中に入れてみましたが(これでは意図と違う表示がされそうですが),結果はおなじでした。 配列tmpの中身を,対応するセルに一つ一つ入れていくにはどのようにしたら良いのでしょうか。 本やネットの情報をつまみ食いして書いているので,理屈やスマートな書き方など よくわかっておらず,見苦しいものかとも思いますがどうぞよろしくお願いします。 ------------------------------ Sub 並べ替え() Dim i As Long, j As Long, m As Long Dim buf As String, tmp As Variant Open "ファイル" For Input As #1 m = 1 Input #1, buf tmp = Split(buf, ",") Cells(1, 1).Value = "X" Cells(1, 2).Value = "Y" Cells(1, 3).Value = "Z" For i = 1 To 960 For j = 1 To 640 m = m + 1 Cells(m, 1).Value = i Cells(m, 2).Value = j Cells(m, 3).Value = tmp Next j Next i Close #1 ChDir "新しいファイル" ActiveWorkbook.SaveAs Filename:="新しいファイル", _ FileFormat:=xlCSV, CreateBackup:=False End Sub ---------------------

  • VBAのプログラムでうまく動かなくて困っています。

    VBA初心者です。 エクセルのVBAのプログラムでうまく動かなくて困っています。教えていただける方がいらしたら、ぜひ教えて下さい!よろしくお願いします。エクセルの内容は以下のとおりです。 (内容) セル    E H J L N P R・・・ 8行目100 200 50 40 30 80 9行目130 350 10 50 60 120 110 ・ ・ (1)列Hの値が列Eの値より大きい場合その下に行を追加します。 (2)セルJ+セルL+セルN+・・をしてセルEの値を超えたセル以降の値を追加した行のセルJ列から順にコピペする処理です。 上のセルの1行目の内容でいいますと、 (1)列Hの値「200」が列Eの値「100」より大きいのでその下に行追加 (2)セルJ、L、N「50」+「40」+「30」でセルEの値「100」より大きいので、追加した行のセルJ列にセルN、Pの値をコピペするです。 以下が私が書いたプログラムです。 Sub test() Dim x As Integer Dim s As Integer Dim t As Integer x = Range("B8").End(xlDown).Row r = Range("J8").End(xlToRight).Column '8行目から最終行までループ For i = x To 9 Step -1 If Cells(i, 5) < Cells(i, 8) Then ☆【For r = y To 11 Step -2 Cells(s, t).Value = Cells(i, r) + Cells(i, r + 2) If Cells(i, 5).Value < Cells(s, t).Value            Then Exit For Next】 Rows(i + 1).Insert Shift:=xlDown '超えたセルをコピーして、1行下の"J列以降"に代入 ★ x = x + 1 End If Next i End Sub 上記プログラムで★の部分がうまく書けません。☆の部分も間違っているような気がします。よろしくお願いします。

  • ExcelのVBAがオーバーフローに!?

    読んで頂きありがとうございます。 以前に質問しました時に回答を頂き凄く助かっていたのですが、何故か「オーバーフロー」と表示されてしまいます。 ひょっとしたら桁なのかも知れません。 下記のVBAを教えて頂きしようしていました。 Option Explicit Sub Test() Dim c(), p(), q(), i, j, l, r, k As Long r = Range("B2").End(xlDown).Row l = Range("D2").End(xlDown).Row ReDim c(r - 2), p(r - 2), q(r - 2) For i = 1 To r - 2 c(i) = Cells(i + 2, 2).Value p(i) = Cells(i + 2, 3).Value q(i) = i + 2 Next i For i = 1 To r - 3 For j = i + 1 To r - 2 If c(i) > c(j) Then k = c(i) c(i) = c(j) c(j) = k k = p(i) p(i) = p(j) p(j) = k k = q(i) q(i) = q(j) q(j) = k End If Next j Next i For i = 1 To r - 2 Cells(i + 2, 7).Value = c(i) For j = 3 To r If Cells(j, 4).Value = c(i) Then Cells(i + 2, 8).Value = p(i) - Cells(j, 5).Value If p(i) - Cells(j, 5).Value <> 0 Then Range("B" & q(i)).Interior.ColorIndex = 6 Range("D" & j).Interior.ColorIndex = 6 End If Exit For End If Next j Next i For i = 3 To r k = 0 For j = 3 To l If Cells(i, 2).Value = Cells(j, 4).Value Then k = 1 Exit For End If Next j If k = 0 Then Range("B" & i).Interior.ColorIndex = 35 End If Next i For i = 3 To l k = 0 For j = 3 To r If Cells(i, 4).Value = Cells(j, 2).Value Then k = 1 Exit For End If Next j If k = 0 Then Range("D" & i).Interior.ColorIndex = 35 End If Next i End Sub デパックのClickすると15行目辺りの「k = c(i)」が黄色くなります。 正直言ってマクロとか全く解りませんが、コピーして使っていました。 どこをどう変更すれば良いのか教えて頂ければ助かります。 よろしくお願いします。

  • VBAで計算を速くできるプログラムは他にありますか

    自己流で書いたのですが、(以下でも答えは合ってはいるのですが、計算結果が出るのが遅いので、もっと速くできるにはどのように書けば良いでしょうか?ご存知の方教えて下さい。 Sub 計算() Dim i, g, u, m, X, A As Integer i = 15 Do Until i = 231 Select Case Cells(i, 1) Case "S" Cells(i, 11) = Cells(i, 5) * Cells(i, 9) Cells(i, 13) = Cells(i, 5) * Cells(i, 9) Cells(i, 14) = 0 Case "R" Cells(i, 11) = Cells(i, 5) * Cells(i, 9) Cells(i, 13) = 0 Cells(i, 14) = Cells(i, 5) * Cells(i, 9) Case "MT" Cells(i, 11) = Cells(i, 5) * Cells(i, 7) * Cells(i, 9) Cells(i, 13) = Cells(i, 5) * 1 * Cells(i, 9) Cells(i, 14) = Cells(i, 5) * 1 * Cells(i, 9) Case "" Cells(i, 11) = "" Cells(i, 13) = "" Cells(i, 14) = "" End Select i = i + 1 Loop i = 15 g = 15 u = 15 Do Until Cells(5, g) = "" For u = 15 To 231 If Cells(u, 1) = "S" Or Cells(u, 1) = "R" Or Cells(u, 1) = "B" Or Cells(u, 1) = "T" Then Cells(u, g) = 0 End If If Cells(u, 1) = "MT" Then Cells(u, g) = Cells(u, 5) * 1 * Cells(u, 9) End If If Cells(u, 1) = "D" Then Cells(u, g) = Cells(u, 5) * Cells(5, g) * Cells(u, 9) End If Next u g = g + 1 Loop u = 15 m = 13 Do Until Cells(10, m) = "" For u = 15 To 231 If Cells(u, 1) = 0 Then Cells(u, 11) = Cells(u, 9) Cells(u, m) = Round(Cells(u, 9) * Cells(10, m), 0) End If Next u m = m + 1 Loop i = 15 X = 15 For i = 15 To 231 If Cells(i, 11) < 0 Then Cells(i, 14).ClearContents End If Next i For i = 15 To 231 If Cells(i, 11) < 0 Then Do Until Cells(i, X) = "" ' A = Cells(i, 14) Cells(i, 14) = Cells(i, X) + A A = Cells(i, 14) X = X + 1 Loop Cells(i, 14) = Cells(i, 11) - Cells(i, 13) - Cells(i, 14) End If X = 15 A = 0 Next i End Sub

  • VBAの乱数について質問

    乱数 x (0<x<1)を0.1刻みで発生させたいんですが うまくいきません。 プログラム例 Sub 一様乱数() Dim bin#(10) n = 1000 For m = 1 To 10 bin#(m) = 0 Next m For J = 1 To n x = Rnd(1) ix = Int(10 * Rnd(1)) bin#(ix) = bin#(ix) + 1 Next J Cells(4, 1) = " I" Cells(4, 2) = "Bin#(I)度数分布" For I = 0 To 10 Cells(I + 5, 1).Value = I Cells(I + 5, 2).Value = bin#(I) Next I End Sub ここで、9行目ix = Int(10 * Rnd(1))で0.1刻みになり 15行目のFor I = 0 To 10を0 to 1に変えればできると思ったんですが できませんでした。 どこが問題なのかヒントでもいいので教えてください。