トップに戻る

クラスモジュールを利用すると、プログラムが簡単かつ便利になった例。


化学計算で例を上げて見ます。

テーマは、化学平衡

硫酸水素ナトリウムと、硫酸を例に取り、濃度に対する、水素イオン濃度を求めました。

例1)
硫酸水素ナトリウム

電離度1として、完全解離とする

平衡定数をk=1.2*10^-2とする

水の解離定数kw=10^-14

硫酸水素ナトリウムの濃度をCとすると、物質収支と、電荷収支をとり、式を整理すると、以下のような式になる。
この方程式の解が水素イオン濃度になります。
この方程式を二分法と、ニュートン方で、計算してみます。

ここで、エクセルのクラスモジュールの使い方に、説明を移したいと思います。
二分法と、ニュートン方の数値計算に関する説明は割愛します。

まず、クラスモジュールを二つ追加します。一つを二分法のプログラムを貼り付け、もう一つに、ニュートン法を貼り付けます。
そのあと、クラス名を変更します。クラス名は、私は、cnibunとcnewtonと付けました。

****************cnibunのソースプログラムです*********************
Option Explicit


Public Function nibun(ByVal a As Double, ByVal b As Double, ByVal of As Object) As Variant


Dim c As Double
Dim seid As Double
Dim change As Double

seid = 0.0000000001
If of.f(a) * of.f(b) > 0 Then
nibun = "解ないかも"
Exit Function
End If

If a = b Then
    nibun = "解ないよ"
Exit Function
End If
If a = 0 Then
    change = b
    b = a
    a = change
End If

Do While gosa(a, b) > seid

    c = (a + b) / 2#
    If of.f(a) = 0 Then
        nibun = a
    Exit Function
    End If
    If of.f(b) = 0 Then
        nibun = b
    Exit Function
    End If
        

    If of.f(a) * of.f(c) < 0 Then
    b = c
    Else
    a = c
    End If

Loop

nibun = (a + b) / 2


End Function

Public Function gosa(a As Double, b As Double) As Double

gosa = Abs((a - b) / a)


End Function

******************cnewtonのプログラムです。********************************
Public Function newton(ByVal x As Double, f4 As Object) As Double
Dim xx As Double

Do While True

xx = x - f4.f(x) / f4.df(x)

If Abs((xx - x) / x) < 0.000000000001 Then Exit Do

x = xx

Loop

newton = xx

End Function

ここで、二分法もニュートン法でも利用する方程式は、新たにクラスモジュールを作り、
そこに作るのが、数値計算のプログラムを汎用性にし、新たな方程式にも、柔軟に対応できるように、なります。

***************方程式のクラスモジュールです*************************************
Option Explicit

Dim CNaHSO4 As Double

'求める解の方程式
Public Function f(h As Double) As Double
Dim k As Double
Dim kw As Double

k = 1.2 * 10 ^ -2
kw = 10 ^ -14

f = h ^ 3 + k * h ^ 2 - (k * CNaHSO4 + kw) * h - k * kw

End Function

'ニュートン法用の一次微分の式
Public Function df(h As Double) As Double
Dim k As Double
Dim kw As Double

k = 1.2 * 10 ^ -2
kw = 10 ^ -14

df = 3 * h ^ 2 + 2 * k * h - (k * CNaHSO4 + kw)

End Function

'硫酸水素ナトリウムの濃度設定
Public Property Get c() As Double

c = CNaHSO4

End Property

Public Property Let c(ByVal vNewValue As Double)

CNaHSO4 = vNewValue

End Property

**********ここまで作ると、後標準モジュールでの利用です。*******************

Option Explicit

Public Sub NaHSO4nibun()
Dim a As New cnibun
Dim b As New NaHSO4
Dim c As New cnewton

'硫酸水素ナトリウムの濃度
b.c = 0.2

Debug.Print a.nibun(1, 10 ^ -14, b), c.newton(1, b)

End Sub
***********計算結果********************************

上記の標準モジュールのプログラムを見ても解るように、二分法と、ニュートン法のオブジェクトを作り、
また、方程式のオブジェクトを作り、数値計算のオブジェクトに方程式のオブジェクトを渡し、計算結果を出しています。

すっきりしたプログラムになっていると思います。
また、プログラムに、細工をして、計算回数を見ると、二分法の方が計算回数に関して多いことがわかります。
では、二分法は、いらないのでは、と言う方もいるかと思います。
ニュートン法の欠点として、一次微分形が、容易に求まらないと、面倒になります。
式が、複雑だと、二分法を使ったほうが便利だなと思う時があります。

次に、硫酸を例に取り、式を複雑なままで、二分法で計算して見ました。

例2)
完全解離の電離度を1とする

あと条件は、例1と同じです。

例一と同様に、物質収支と電荷収支をとって、式を作ると
整理すれば、良いのですが、今回は、ワザと整理しませんでした。

*****************方程式のクラスモジュールを作ります*****************************
Option Explicit

Dim CH2SO4 As Double

Public Function f(h As Double) As Double
Dim k As Double
Dim kw As Double
Dim w As Double

k = 1.2 * 10 ^ -2
kw = 10 ^ -14

w = h / (k + h)

f = h ^ 2 - (2# - w) * CH2SO4 * h - kw


End Function

Public Property Get c() As Double

c = CH2SO4

End Property

Public Property Let c(ByVal vNewValue As Double)

CH2SO4 = vNewValue

End Property

****************よって、標準モジュールは、以下のようになりました。******************
Public Sub H2SO4()
Dim a As New cnibun
Dim b As New H2SO4

'硫酸濃度
b.c = 0.01

Debug.Print a.nibun(1, 10 ^ -14, b)


End Sub
計算結果は

よって、クラスモジュールを利用すると、プログラミングに汎用性ができます。

便利とは、思いませんか。