複雜的函式結構Equation

引入: 自定義

 

結構Equation 是用來描述一個「函式」,該函式可以包含一個變數,並且做簡單的數值代入運算、求極近似根(尚不成熟)、微積分,有些情況下,可以使用二分法求解。

 

為什麼叫Equation 是因為Function 被用來定義程式語言的函式方法,Func 則是Visual Basic 內建的Lambda 方程式,而不是寫手我一點英文或數學基礎都沒有。

 

為了讀懂這個Equation 的結構,我們必須知道幾個特別的函式。首先,SeemToBeEqual 是一個非常沒必要的東西,她是用來讓電腦認為"1 * 10 ^ (-100)" 跟"2 * 10 ^ (-100)" 等值,因為差距太小忽略不計。

]Function SeemToBeEqual(ByVal Input As Array, Optional ByVal Precise As Integer = 15) As Boolean

]If (Input Is Nothing) Then

]Return False

]End If

]For i1 As Integer = LBound(Input) To UBound(Input) Step 1

]If (((Input(i1) - Input(i1 + 1)) ^ 2) ^ (1 / 2) <= 10 ^ (-Precise)) Then

]Return False

]End If

]Next

]Return True

]End Function

 

接著是SafeExponent,用來預防零的次方指數為負數狀況。參數是SafeExponent(底數, 指數)。

]Function SafeExponent(ByVal Main As Object, ByVal Exponent As Object, Optional ByVal SafeOut As Object = 0) As Object

]If (Main = 0) Then

]Select Case Stick(Exponent, 0)

]Case 0

]Return 1

]Case -1

]Return SafeOut

]End Select

]End If

]Return Main ^ Exponent

]End Function

 

現在可以來看主體程式了。其中Modulus 用來記錄一個函式的各項係數,並且是以升冪排列,舉個例子,"x^3 + 2x^2 + 3x + 4" 是個降冪排列式,升冪式為"4 + 3x + 2x^2 + x^3",那個Modulus 就是各項係數{4, 3, 2, 1}。LowDeg 指的是Modulus 第一個係數的次方,比如說"2x^2 + x" 可以表示成Modulus = {0, 1, 2} 並且LowDeg = 0,也可以簡單表示成Modulus = {1, 2} 且LowDeg = 1。

]Structure Equation

]Dim Modulus As Array

]Dim LowDeg As Integer

]

]Function Value(ByVal X As Object) As Object

]Value = 0

]For i1 As Integer = LBound(Modulus) To UBound(Modulus) Step 1

]Value += Modulus(i1) * SafeExponent(X, i1 + LowDeg)

]Next

]Return Value

]End Function

]

]Function Root(ByVal TheValue As Equation, Optional ByVal Per As Object = 1, Optional ByVal RootAmount As Integer = -1, Optional ByVal TryLevel As Integer = 10, Optional ByVal TryUp As Object = 20, Optional ByVal TryDown As Object = -20, Optional ByVal Trying As Double = 2 / 3) As Array

]If (Modulus Is Nothing) Then

]Return Nothing

]End If

]If (RootAmount <= 0) Then

]RootAmount = UBound(Modulus) - LBound(Modulus) + LowDeg

]End If

]Dim Result As Array

]Dim Over As Boolean = False

]For TryLevelIndex As Integer = 0 To TryLevel Step 1

]For StepIndex As Object = 0 To TryUp / (Per * (Trying ^ TryLevelIndex)) Step (Per * (Trying ^ TryLevelIndex))

]Dim TheX As Object = StepIndex * (Per * (Trying ^ TryLevelIndex))

]If (SeemToBeEqual(New Object() {Value(TheX), TheValue.Value(TheX)})) Then

]Dim NoRepeat As Boolean = True

]If Not (Result Is Nothing) Then

]For i1 As Integer = LBound(Result) To UBound(Result) Step 1

]If (SeemToBeEqual(Result(i1), TheX)) Then

]NoRepeat = False

]Exit For

]End If

]Next

]End If

]If (NoRepeat) Then

]Result = ResPush(Result, TheX)

]End If

]If Not (Result Is Nothing) Then

]If (UBound(Modulus) - LBound(Modulus) + 1) Then

]Over = True

]Exit For

]End If

]End If

]End If

]Next

]If (Over) Then

]Exit For

]End If

]For StepIndex As Object = 0 To TryDown / (Per * (Trying ^ TryLevelIndex)) Step -(Per * (Trying ^ TryLevelIndex))

]Dim TheX As Object = StepIndex * (Per * (Trying ^ TryLevelIndex))

]If (SeemToBeEqual(Value(TheX), TheValue.Value(TheX))) Then

]Dim NoRepeat As Boolean = True

]If Not (Result Is Nothing) Then

]For i1 As Integer = LBound(Result) To UBound(Result) Step 1

]If (SeemToBeEqual(New Object() {Result(i1), TheX})) Then

]NoRepeat = False

]End If

]Next

]End If

]If (NoRepeat) Then

]Result = ResPush(Result, TheX)

]End If

]If Not (Result Is Nothing) Then

]If (UBound(Modulus) - LBound(Modulus) + 1 >= RootAmount) Then

]Exit For

]End If

]End If

]End If

]Next

]If (Over) Then

]Exit For

]End If

]Next

]Return Result

]End Function

]

]Function Bisection(ByVal Least As Object, ByVal Most As Object, Optional ByVal Precise As Integer = 15) As Object

]If (SeemToBeEqual(New Object() {Value(Least), 0})) Then

]Return Least

]End If

]If (SeemToBeEqual(New Object() {Value(Most), 0})) Then

]Return Most

]End If

]If Not (Value(Least) * Value(Most) < 0) Then

]Return 0

]End If

]Do Until Most - Least < 10 ^ (-Precise)

]Dim Middle As Object = (Most + Least) / 2

]If (SeemToBeEqual(New Object() {Value(Middle), 0})) Then

]Return Middle

]End If

]If (Value(Middle) * Value(Least) >= 0) Then

]Least = Middle

]ElseIf (Value(Middle) * Value(Most) >= 0) Then

]Return Most

]End If

]Loop

]Return (Most + Least) / 2

]End Function

]

]Function Differential(Optional ByVal Level As Integer = 1) As Equation

]If (Modulus Is Nothing) Then

]Return Nothing

]End If

]If (Level < 0) Then

]Return Integral(, 0 - Level)

]End If

]With Differential

].LowDeg = LowDeg

].Modulus = God(Modulus, ResDim(.Modulus, UBound(Modulus) - LBound(Modulus)))

]For i1 As Integer = 1 To Level Step 1

]For ModulusIndex As Integer = LBound(.Modulus) To UBound(.Modulus) Step 1

].Modulus(ModulusIndex) *= (ModulusIndex + .LowDeg)

]Next

].LowDeg -= 1

]Next

]End With

]Return Differential

]End Function

]

]Function Integral(Optional ByVal C As Object = 0, Optional ByVal Level As Integer = 1) As Equation

]If (Modulus Is Nothing) Then

]Return Nothing

]End If

]If (Level < 0) Then

]Return Differential(0 - Level)

]End If

]With Integral

].LowDeg = LowDeg

].Modulus = God(Modulus, ResDim(.Modulus, UBound(Modulus) - LBound(Modulus)))

]For i1 As Integer = 1 To Level Step 1

]For ModulusIndex As Integer = LBound(.Modulus) To UBound(.Modulus) Step 1

].Modulus(ModulusIndex) /= (ModulusIndex + .LowDeg + 1)

]Next

].LowDeg += 1

]Next

]Do Until (.LowDeg) * (.LowDeg + UBound(.Modulus) - LBound(.Modulus)) <= 0

]Select Case Stick(.LowDeg, 0)

]Case 1

].Modulus = ResPush(.Modulus, 0, 0)

].LowDeg += 1

]Case -1

].Modulus = ResPush(.Modulus, 0)

]End Select

]Loop

].Modulus(0 - .LowDeg) = C

]End With

]Return Integral

]End Function

]

]Sub New(ByVal NewModulus As Array, Optional ByVal NewLowDeg As Integer = 0)

]Modulus = NewModulus

]LowDeg = NewLowDeg

]End Sub

]End Structure

 

也許各位高手們會覺得裡面給函式的取名很奇怪,不過有些函式的功能是跟命名當時不一樣的,個人是沒在意那麼多。

 

原理方面,Value 是直接把X 代入求值,但是Equation 可以包容負數的X 次項,如果遇到0 ^ (-1) 這類的,Visual Basic 可能會傳回1 或-1 等奇怪的數值,而我則是統一定為0。

 

Root(另一個函式) 看得出來有很多參數,是在求當前函式與該函式的交點,取名為Root 是因為當初沒有TheValue 參數。其中RootAmount 是已知的根的數量,應該不難看出來這個函式使用的是「暴力破解」的方法,這些參數就是破解時從0 以Per 為一步開始破解到TryUp,然後回到0,往負數破解到TryDown,如果還沒破解完畢,就把「步寬」──Per 縮小,縮小的比例就是Trying。程式裡有很多地方有判斷破解出來的根是否已達已知數量RootAmount,這是為了縮短破解時間,即使如此,在使用這個函式仍然需要一段讓電腦十分疲勞的時間。

 

Bisection 就如其字面意義,是二分法求解。從這個函式的結構看得出來很不可靠。

 

Differential 是微分,Level 是微分幾次,也就是N 階微分式。Integral 是積分,Level 也是階次。積分函式的結構中,當所有積分完畢,會開始檢查Modulus 陣列裡是否有零次方項,因為C 必須被存入。

文章標籤
全站熱搜
創作者介紹
創作者 GPhettoH 的頭像
GPhettoH

歇息,等待明日的天空

GPhettoH 發表在 痞客邦 留言(0) 人氣(29)