|
▼ジュン さん:
こんばんは。
>以前の問題と似ているのですが,新たな問題を課せられて困っています.
本当はね、前回のコードをじっくり見ていただいて理解していただくと
以下の問題のアルゴリズムはわかってくると思うのですが・・・。
>
>Tn=A*Pn+B*((Σ(i=1⇒n)Wi×Pn-i)-(Σ(i=1⇒n)Wi×Tn-i))
>という数値計算を行いたいとき,
>A=B=定数
>T0=P0=0
>Pn:=nのときの値(既知)
>Wi:i=1〜nのときの値(既知)
>が与えられたときのTnの値を求めたいのですが,
>
>例えば,
>A=10
>B=20
>n=5
>Pn=1,2,3,4,5 (n=1〜5)
>Wi=0.2,0.4,0.6,0.8,1.0 (i=1〜5)
例題として、
・P0及び、Pn(1〜5)は、
アクティブシートのセルA1〜A6に0,1,2,3,4,5と入力して下さい。
・Wi(1〜5)は、セルB2〜B6に0.2,0.4,0.6,0.8,1と入力して下さい。
コードは、以下のとおりです。前回のコードとは違うコードも記述されていますが、
もっうちょっと使いやすくした結果です。
'===============================================================
Sub test()
MsgBox newtn(5, 0, Range("a1:a6"), Range("b2:b6"), 10, 20)
End Sub
'===========================================================
Function newtn(n As Long, t0 As Variant, _
p_rng As Range, _
w_rng As Range, _
a As Variant, _
b As Variant)
'newTn=A*Pn+B*((Σ(i=1⇒n)Wi×Pn-i)-(Σ(i=1⇒n)Wi×Tn-i))を計算する
'input : n 求めたい数列値、t0--初期値
' p_rng p0〜pnに相当するセル範囲
' w_rng w1〜wnに相当するセル範囲
' a 、b 定数
'output: newtn 結果
Dim idx As Long
Dim jdx As Long
Dim pn() As Variant
Dim wn() As Variant
Dim Swixpnm1 As Variant
Dim Swixtnm1 As Variant
ReDim ans(n) As Variant
'この'***********で挟んである間のコードはあまり気にしないでよいです
'ただ、指定されたセル範囲データの配列変数にセットしなおしているだけです
'************************************************************
With p_rng
If .Rows.Count > 1 Then
ReDim pn(.Rows.Count)
For idx = 1 To .Rows.Count
pn(idx - 1) = CDec(.Cells(idx, 1).Value)
Next idx
ElseIf .Columns.Count > 1 Then
ReDim pn(.Columns.Count)
For idx = 1 To .Columns.Count
pn(idx - 1) = CDec(.Cells(1, idx).Value)
Next idx
Else
ReDim pn(0)
pn(0) = CDec(Cells(1, 1).Value)
End If
End With
With w_rng
If .Rows.Count > 1 Then
ReDim wn(1 To .Rows.Count)
For idx = 1 To .Rows.Count
wn(idx) = CDec(.Cells(idx, 1).Value)
Next idx
ElseIf .Columns.Count > 1 Then
ReDim wn(1 To .Columns.Count)
For idx = 1 To .Columns.Count
wn(idx) = CDec(.Cells(1, idx).Value)
Next idx
Else
ReDim wn(0)
wn(0) = CDec(Cells(1, 1).Value)
End If
End With
'***********************************************************
'問題解決のコードはここからです
'
ans(0) = CDec(t0)
For idx = 1 To n
Swixpnm1 = 0
Swixtnm1 = 0
For jdx = idx - 1 To 0 Step -1
Swixpnm1 = Swixpnm1 + wn(idx - jdx) * pn(jdx)
Swixtnm1 = Swixtnm1 + wn(idx - jdx) * ans(jdx)
Next
ans(idx) = CDec(a) * pn(idx) + CDec(b) * (Swixpnm1 - Swixtnm1)
Next
newtn = ans(UBound(ans()))
End Function
Cdec関数というのが出てきていますが、小数計算の小さい誤差がでないように
使いました(これは、前回のコードにも入れたほうがよさそうです)
アルゴリズムの基本的なところは変わっていません。
上記の「newtn」は、ワークシート関数としても使えます。
例えば、セルC6に「=newtn(5,0,$A$1:$A$6,$B$2:$B$6,10,20)」
という数式を指定して確認してみて下さい。
こういうの漸下式って言うんでしたっけ?
こういう式からループのアルゴリズムを書くのは良い練習問題になりますよ!!
|
|