計算プリントを生成する 文字式の計算 その2(2aと3a^2の四則の計算)
はじめに
今回は2aと3a2の四則の計算を行います。
ちょっとややこしいところです。
手動でやってみる
文章題で思いましたが、手動でやってみることって大事ですね。
癖が見えてきます。
計算式 | 答え |
---|---|
2a+3a2 | 2a+3a2 |
2a-3a2 | 2a-3a2 |
2a×3a2 | 6a3 |
2a÷3a2 | 2/3a |
難解な点が二か所。
答えが多項式になるところ(足し算と引き算)と
答えが分数になり分母に文字が来るところ(割り算)です。
この2つをクリアすることが今回の課題です。
自動でやってみる
正直まだ理解しきれていないところがあって、とにかくコードが複雑です。
Literal2クラス
分数にも対応しているLiteralクラスです。
一応Literalクラスと別に作成しました。
Public Va As Integer Public Vb As Integer Private La_ As String Private Lb_ As String Private element(1 To 26) As Integer Private Sub Class_Initialize() Va = 0 Vb = 1 End Sub Property Get La() As String La = La_ End Property Property Let La(str As String) La_ = str Dim i As Integer '繰り返しの制御変数 Dim trgt As String 'element作成のアシスト変数 Dim num As Integer 'element作成のアシスト変数 '--------------- 'elementに仕分け '--------------- For i = 1 To Len(str) trgt = Mid(str, i, 1) num = Asc(trgt) - 96 Select Case num Case Is < 1 Stop Case Is < 27 element(num) = element(num) + 1 Case Else Stop End Select Next End Property Property Get Lb() As String Lb = Lb_ End Property Property Let Lb(str As String) Lb_ = str Dim i As Integer '繰り返しの制御変数 Dim trgt As String 'element作成のアシスト変数 Dim num As Integer 'element作成のアシスト変数 '--------------- 'elementに仕分け '--------------- For i = 1 To Len(str) trgt = Mid(str, i, 1) num = Asc(trgt) - 96 Select Case num Case Is < 1 Stop Case Is < 27 element(num) = element(num) - 1 Case Else Stop End Select Next End Property Function Fit() '-------------- '整形 '-------------- '-------------- '変数の定義 '-------------- Dim i As Integer '繰り返しの制御変数 Dim L As Integer '約分のアシスト変数 Dim ansa As String '文字分配のアシスト変数 Dim ansb As String '文字分配のアシスト変数 Dim trgt As String '文字分配のアシスト変数 '-------------- '正負の考慮 '-------------- If Vb < 0 Then Va = Va * -1 Vb = Vb * -1 End If '-------------- '約分 '-------------- If Va = 0 Then Exit Function End If L = Application.WorksheetFunction.Gcd(Abs(Va), Abs(Vb)) Va = Va / L Vb = Vb / L '--------------- '文字の分配 '--------------- For i = 1 To 26 trgt = Chr(96 + i) Select Case element(i) Case Is < -1 ansb = ansb & trgt & "^" & Abs(element(i)) Case Is = -1 ansb = ansb & trgt Case Is = 1 ansa = ansa & trgt Case Is > 1 ansa = ansa & trgt & "^" & element(i) End Select Next La_ = ansa Lb_ = ansb End Function Property Get S() As String '----------------- 'V,L_からSを作成 '----------------- '----------------- '変数の定義 '----------------- Dim ansa As String '分子 Dim ansb As String '分母 Call Fit Select Case True Case La_ = "" ansa = Va Case Va = 0 ansa = "" Case Va = 1 ansa = La_ Case Va = -1 ansa = "-" & La_ Case Else ansa = Va & La_ End Select Select Case True Case Lb_ = "" If Vb = 1 Then ansb = "" Else ansb = Vb End If Case Vb = 0 Stop Case Vb = 1 ansb = Lb_ Case Vb = -1 ansb = "-" & Lb_ Case Else ansb = Vb & Lb_ End Select If ansa = "" Then S = 0 ElseIf ansb = "" Then S = ansa Else S = ansa & "/" & ansb End If End Property
Lit_Str_Make_2
Literal2クラスに対応した関数です。
Function Lit_Str_Make_2(NN) As String '------------------- '文字式の計算式を作成する '------------------- '------------------ '変数の定義 '------------------ Dim ope() As String '演算子 Dim kou() As Literal2 '数値 Dim i As Integer '繰り返しの制御変数 Dim box As Variant '演算子決定のアシスト変数 Dim tmp As Integer '演算子決定のアシスト変数 Dim str As String '計算式 Dim ans As String '計算式の答え '------------------ 'opeとnumの配列数を指定 '------------------ ReDim ope(1 To NN) ReDim kou(1 To NN) '------------------ 'boxの指定 '------------------ box = Array("+", "-", "×", "÷") '------------------ 'opeの値を指定 '------------------ For i = 1 To NN - 1 tmp = Rnd_Num(0, 3) ope(i) = box(tmp) Next ope(2) = "=" '------------------ 'kouの値を指定 '------------------ Set kou(1) = New Literal2 kou(1).Va = 2 kou(1).La = "a" Set kou(2) = New Literal2 kou(2).Va = 3 kou(2).La = "aa" '------------------ 'ansを計算 '------------------ ans = Lit_Calculation_2(kou, ope) '------------------ 'ansを作成 '------------------ For i = 1 To NN str = str & kou(i).S & ope(i) Next str = str & ans Lit_Str_Make_2 = str End Function
Lit_Calculation_2
こちらもLiteral2クラス対応の関数。
2項の計算専用にしているため、あまり汎用性はありません。
Function Lit_Calculation_2(ByVal kou, ope) As String '------------------ '2項の文字式の計算 '------------------ Dim ans As Literal2 Dim ans2 As String Set ans = New Literal2 Select Case ope(1) Case Is = "+" If kou(1).La = kou(2).La And kou(1).Lb = kou(2).Lb Then ans.Va = kou(1).Va * kou(2).Vb + kou(1).Vb * kou(2).Va ans.Vb = kou(1).Vb * kou(2).Vb ans.La = kou(1).La ans.Lb = kou(1).Lb Else ans2 = kou(1).S & ope(1) & kou(2).S Lit_Calculation_2 = ans2 Exit Function End If Case Is = "-" If kou(1).La = kou(2).La And kou(1).Lb = kou(2).Lb Then ans.Va = kou(1).Va * kou(2).Vb - kou(1).Vb * kou(2).Va ans.Vb = kou(1).Vb * kou(2).Vb ans.La = kou(1).La ans.Lb = kou(1).Lb Else ans2 = kou(1).S & ope(1) & kou(2).S Lit_Calculation_2 = ans2 Exit Function End If Case Is = "×" ans.Va = kou(1).Va * kou(2).Va ans.Vb = kou(1).Vb * kou(2).Vb ans.La = kou(1).La & kou(2).La ans.Lb = kou(1).Lb & kou(2).Lb Case Is = "÷" ans.Va = kou(1).Va * kou(2).Vb ans.Vb = kou(1).Vb * kou(2).Va ans.La = kou(1).La & kou(2).Lb ans.Lb = kou(1).Lb & kou(2).La End Select Lit_Calculation_2 = ans.S End Function``` ここはかなり汎用性を削っています。 それでも2項の計算ならできるので良しとします。 できる範囲でとにかく作る。が大事だと思っています。 ###まとめ これでとりあえず2a,3a^2の四則の計算はクリアです。 ついでにどんな2項の計算でも(たぶん)できるようになりました。 次にやることは迷いますね。 右の道は楽の看板。 文字式への代入です。 左の道は覚悟の看板。 3項以上の文字式の計算です。 んー。 今勢いに乗っているので、3項以上の文字式の計算をやりましょう。 無理そうだったらできるところまでで凍結しますが、現時点で出来るところまでやりましょう。