下記の記事
https://qiita.com/yanasep/items/503b378c439752f70880
を参考にしながら電卓を作成しました。
数字ボタン
初期値の0だったら、ボタンの数字を入れ、それ以外だったら、入力した値を追加して行きます。
zero.setOnClickListener{
if (calc_display.text == "0") calc_display.text = "0"
else calc_display.text = "${calc_display.text}0"
inputNum += "0"
}
one.setOnClickListener{
if (calc_display.text == "0") calc_display.text = "1"
else calc_display.text = "${calc_display.text}1"
inputNum += "1"
}
...
###演算子ボタン
addInput()でinputNum(文字型)をdoubleに変換して配列に格納。
演算子も演算子用の配列に格納。
inputNumは次の数値入力のため初期化します。
plus.setOnClickListener{
calc_display.text = "${calc_display.text}+"
addInput(inputNum,'+')
inputNum = ""
}
minus.setOnClickListener{
calc_display.text = "${calc_display.text}-"
addInput(inputNum,'-')
inputNum = ""
}
...
private fun addInput(inputNum:String, ope:Char){
try {
var num = inputNum.toDouble()
numList.add(num)
if (ope != '=') opeList.add(ope)
}catch(e:Exception){
calc_display.text = "Numeric Error"
}
}
=ボタンは、計算処理が入ります。
equel.setOnClickListener{
calc_display.text = ""
addInput(inputNum, '=')
val result = calculation().toBigDecimal()
calc_display.text = result.stripTrailingZeros().toPlainString()
inputNum = ""
numList.clear()
opeList.clear()
}
calculation()の戻り値は下記の理由によりdoubleからStringに変換した物を戻り値にして、その後にBigdecimal型に変換しています。
https://www.ne.jp/asahi/hishidama/home/tech/java/math/bigdecimal.html
BigDecimal自身は10進数の固定小数を扱えるのだが、doubleを使って初期化する場合、doubleは2進数の浮動小数なので、BigDecimalに変換する際に小数点以下の値が変わってしまうことがある。
その為、小数を扱いたい場合は、doubleを使わず、Stringで初期化する方がよい。
val result = calculation().toBigDecimal()
小数点第一位が0の時に整数として表示するため0削除と文字型に変換。
BigDecimal使用時にtoString()を呼ぶと指数表記になることがあるため、toPlainString()を使用。
calc_display.text = result.stripTrailingZeros().toPlainString()
calculation()
徐算と乗算を先に行います。
numListを計算した数に置き換え、次の数を削除します。
入力例
1*3/4-5+10
numList[2,3,4,5,10]
opeList[*,/,-,+]
while (i < opeList.size)の処理
1
2*3が行われ、3が消える。
合計の6が代入される。
numList[6,4,5,10]
opeList[/,-,+]
opeList.size=3
i=0
2
6/4が行われ1.5が代入される。
4は消える。
numList[1.5,5,10]
opeList[-,+]
opeList.size=2
i=0
3
-を負の数に変換。
opeListを+に変更。
numList[1.5,-5,10]
opeList[+,+]
opeList.size=2
i=1
4
+だったため特に何もしない。
numList[1.5,-5,10]
opeList[+,+]
opeList.size=2
i=2
for(i in numList)の処理
numList[1.5,-5,10]
の内容を全て足しています。
private fun calculation():String {
var i = 0
var result = 0.0
while (i < opeList.size){
if(opeList.get(i) == '/' || opeList.get(i) == '*'){
if(opeList.get(i) == '*') result = numList.get(i) * numList.get(i+1)
else result = numList.get(i) / numList.get(i+1)
numList.set(i,result) //計算に使った一つ目の数を計算結果に置き換え
numList.removeAt(i+1) //二つ目の数をリストから削除
opeList.removeAt(i) //使い終わった演算子をリストから削除
i-- //リストの次の要素が一つ手前に来たのでiを一つ戻す
} else if (opeList.get(i) == '-') {
opeList.set(i, '+')
numList.set(i + 1, numList.get(i + 1) * -1) //引かれる数をマイナスにしてあとでまとめて足す
}
i++
}
result = 0.0
for(i in numList){
result += i
}
return result.toString()
}