#はじめに
皆さんはじめまして。
化学を専門に勉強している学生がプログラミングに手を出してみました。
今回作成したプログラムは科学分野で広く"濃度"の単位として用いられている"Parts Par表記の相互換算を行うプログラムです。
#Parts Par 表記とは
Parts Par表記は厳密には"無次元数"と呼ばれる単位で、全体に対して目的としている物がどの程度の割合で存在しているかを表しています。
存在している割合が
百万分の一ならparts par million(ppm)
十億分の一ならparts par billion(ppb)
一兆分の一ならparts par trillion(ppt)
千兆分の一ならparts par quadrillion(ppq)
になります。
#作成した背景
同級生に単位換算が苦手な学生がおり、検算を頼まれた時に「これ、プログラムにしてしまえば手っ取り早いのでは?」と思ったため。
ただし、パソコンが近くにない場合やパソコンが起動していない場合だと余計な手間がかかってしまうのが問題ですね。
#今回の作成環境
Microsoft Visual Studio
VisualBasic Windows フォームアプリケーション(.NET Framework)
##使い方
1.いずれかのテキストボックスに数値を入力
2.コンボボックスから変換元の濃度を指定
3.コンバートボタンで変換を実行
4.他のテキストボックスへ結果を出力
#ソースコードの解説
・具体的な値を処理する変数では、桁数の大きい小数を取り扱うのでDouble(倍精度浮動小数型)で定義しました。
・String(文字列型)で濃度の名前(4つ分)とエラーメッセージを取り扱う変数をそれぞれ定義しました。
・変換元のデータの判定結果を格納する"ric"とエラー時に利用するための"conti"を定義します。これらに入る数値は整数なのでInteger(整数型)で定義。
(以降まとめて話す場合には"管理用変数"と表記します。)
・メッセージボックスの書式を決定するためのStyle_crをMsgBoxStyleで定義しました。
Text All ClearなのでTACL()という名前になっています。
初期化用のSubプロシージャをTACL()で呼び出して、各テキストボックスを空欄にして、管理用変数を0にします。
次に、濃度の名前を配列"concentration"にそれぞれ入力します。
配列に入れた濃度名をFor文を使ってコンボボックスに登録していきます。
この方法は複数のコンボボックスに同じ内容を登録する際に重宝します。
メッセージボックスの書式設定では次の内容を規定しています。
・クリティカル(赤い×印のアイコンのメッセージボックス)
・アプリケーションモーダル(ユーザーがメッセージボックスに何らかのリアクションをしない限り、前の画面に戻らせないようにする)
・メッセージボックスセットフォアグラウンド(表示するメッセージボックスを最前面に表示せよ)
・システムモーダル(ユーザーがメッセージボックスに何らかのリアクションをしない限り、プログラムの処理を再開させないようにする)
この部分で、コンボボックスの中身をSelect Caseを用いて判断しています。
以下、指定の濃度別に計算処理を行っていきます。
ppmでの計算を例に解説します。
まずはじめにcalにテキストボックス1の文字列をVal(数値)として取り込みます。
次に正規化処理を行い、0~9と小数以外の文字列の有無を判定します。
規定文字列以外が含まれている場合、0以下の数値の場合には
"適切な数値を入力してください。"
"エラー内容:未入力、非数値、0以下の数値の入力"
のメッセージを表示し、contiの値を0にします。
入力された文字列に問題がない場合には、contiを1とし、計算用Subプロシージャに飛びます。
CalculationなのでCA()という名前になっています。
入力された値がconに格納されています。
If文を用いて、conの値が10以上であるか、1以下であるかを判定します。
これは、科学的な計算のルールである有効数字というものを考慮するための処理です。
0以上1以下の数字の部分(係数)と10の累乗の形で表記することで、何桁目までが正確な値かが分かります。
(例:120.3 cmのロープを10 cm刻みの定規で測ると1.2×10^2 cmとなり、1 cm刻みの定規ではかると1.203×10^2 cmとなります)
calc(1)に10の何乗か(指数)を格納します。
conの値が10以上ならば、10で割って、指数を+1します。
conの値が1未満ならば、10を掛けて、指数を-1します。
また、calc(2)に係数を格納します。
次にそれぞれの濃度になるように指数部分を調整します。
ppm=10^(-6)、ppb=10^(-9)、よってppmからppbへは10^(3)大きな値になります。そのためcalc(1)に3を足します。
それぞれ指数の調整が完了したら、係数と指数を掛け合わせて各テキストボックスへ出力します。
また、contiが0の場合には、テキストボックス1~4に"Error"と出力するように以下のSubプロシージャを呼び出しています。
##ボタン1(コンバートボタン)での処理(続き)
以下同様に各濃度での処理を行っていきます。
なお、変換元のデータが規定されていない場合には、次のプログラムでエラーメッセージを出力します。
初期化SubプロシージャをTACL()で呼び出しています。
Me.Close()でプログラムを終了しています。
#ソースコード全体
Public Class Form1
Dim con, calc(2) As Double 'データ引き込み用と計算用の入れ物
Dim concentration(3), er_msg As String '濃度指定の入れ物とエラーメッセージの入れ物
Dim ric, conti As Integer '行動管理用の入れ物
Dim style_cr As MsgBoxStyle 'メッセージ用の設定
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Select Case ComboBox1.Text '変換元のデータ指定
Case concentration(0) 'ppm
ric = 1
Case concentration(1) 'ppb
ric = 2
Case concentration(2) 'ppt
ric = 3
Case concentration(3) 'ppq
ric = 4
End Select
If ric = 1 Then 'ppm
con = Val(TextBox1.Text)
If Not (System.Text.RegularExpressions.Regex.IsMatch(TextBox1.Text, "[^0-9.]")) And con > 0 Then
conti = 1
Else
conti = 0
MsgBox(er_msg, style_cr, "処理不能な値")
End If
CA()
TextBox2.Text = calc(2) * 10 ^ (calc(1) + 3) 'ppm => ppb
TextBox3.Text = calc(2) * 10 ^ (calc(1) + 6) 'ppm => ppt
TextBox4.Text = calc(2) * 10 ^ (calc(1) + 9) 'ppm => ppq
con = 0
If conti = 0 Then 'エラー時にエラーと表示させる
ABAL()
End If
ElseIf ric = 2 Then 'ppb
con = Val(TextBox2.Text)
If Not (System.Text.RegularExpressions.Regex.IsMatch(TextBox2.Text, "[^0-9.]")) And con > 0 Then
conti = 1
Else
conti = 0
MsgBox(er_msg, style_cr, "処理不能な値")
End If
CA()
TextBox1.Text = calc(2) * 10 ^ (calc(1) - 3) 'ppb => ppm
TextBox3.Text = calc(2) * 10 ^ (calc(1) + 3) 'ppb => ppt
TextBox4.Text = calc(2) * 10 ^ (calc(1) + 6) 'ppb => ppq
con = 0
If conti = 0 Then 'エラー時にエラーと表示させる
ABAL()
End If
ElseIf ric = 3 Then 'ppt
con = Val(TextBox3.Text)
If Not (System.Text.RegularExpressions.Regex.IsMatch(TextBox3.Text, "[^0-9.]")) And con > 0 Then
conti = 1
Else
conti = 0
MsgBox(er_msg, style_cr, "処理不能な値")
End If
CA()
TextBox1.Text = calc(2) * 10 ^ (calc(1) - 6) 'ppt => ppb
TextBox2.Text = calc(2) * 10 ^ (calc(1) - 3) 'ppt => ppm
TextBox4.Text = calc(2) * 10 ^ (calc(1) + 3) 'ppt => ppq
con = 0
If conti = 0 Then 'エラー時にエラーと表示させる
ABAL()
End If
ElseIf ric = 4 Then 'ppq
con = Val(TextBox4.Text)
If Not (System.Text.RegularExpressions.Regex.IsMatch(TextBox4.Text, "[^0-9.]")) And con > 0 Then
conti = 1
Else
conti = 0
MsgBox(er_msg, style_cr, "処理不能な値")
End If
CA()
TextBox1.Text = calc(2) * 10 ^ (calc(1) - 9) 'ppq => ppb
TextBox2.Text = calc(2) * 10 ^ (calc(1) - 6) 'ppq => ppm
TextBox3.Text = calc(2) * 10 ^ (calc(1) - 3) 'ppq => ppt
con = 0
If conti = 0 Then 'エラー時にエラーと表示させる
ABAL()
End If
Else 'ric=0 つまり未選択
MsgBox("変換元のデータが指定されていません", style_cr, "変換元不明")
Exit Sub
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TACL() '初期化操作
concentration(0) = "ppm"
concentration(1) = "ppb"
concentration(2) = "ppt"
concentration(3) = "ppq"
For i = 0 To 3 Step 1 'コンボボックスにアイテムを追加する
ComboBox1.Items.Add(concentration(i))
Next i
'メッセージボックスのスタイル設定
style_cr = MsgBoxStyle.Critical Or MsgBoxStyle.ApplicationModal Or MsgBoxStyle.MsgBoxSetForeground Or MsgBoxStyle.SystemModal
er_msg = "適切な数値を入力してください。" & vbCrLf & "エラー内容:未入力、非数値、0以下の数値の入力"
End Sub
Private Sub Button3_Click_1(sender As Object, e As EventArgs) Handles Button3.Click '終了ボタン
Me.Close()
End Sub
Private Sub TACL() '初期化操作部
TextBox1.Text = ""
TextBox2.Text = ""
TextBox3.Text = ""
TextBox4.Text = ""
ComboBox1.Text = "変換元の濃度を指定"
con = 0
ric = 0
conti = 0
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click '初期化ボタン
TACL()
End Sub
Private Sub CA() '計算処理部
If con > 0 Then '桁数判断
While con > 10 '10より大きいならば10で割って指数+1
con /= 10
calc(1) += 1
End While
Else
While con >= 1 '1以下ならば10倍して指数-1
con *= 10
calc(1) -= 1
End While
End If
calc(2) = con / 10 ^ (calc(1)) '係数の算出
End Sub
Private Sub ABAL() 'すべてのTextBoxにエラーと表示せよ
TextBox1.Text = "Error"
TextBox2.Text = "Error"
TextBox3.Text = "Error"
TextBox4.Text = "Error"
End Sub
End Class
#最後に
久しぶりのプログラミングだったので、「あれ?ここのコードってどうやって書くんだったっけ?」となりました。
やっぱり書かないと忘れますね。特に正規化のあたりとか。
次回は規定濃度の溶液をこの量作るためには原液が何mL必要かを計算するプログラムや何倍希釈・濃縮なのかを計算するようなプログラムを作ろうかなと考えています。
このプログラムがいつの日か、どこかの誰かの役に立つといいな。