滝の音

滝の音

名こそ流れてなお聞こえけれ

計算プリントを生成する 文字式の計算 その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項以上の文字式の計算をやりましょう。  
無理そうだったらできるところまでで凍結しますが、現時点で出来るところまでやりましょう。