複雜的函式結構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 必須被存入。
