【電卓アプリを作るvol.6】計算結果を成型する
前回まで・・・
とりあえず、必要最低限の電卓ができました。
今回は、計算結果を丸めて表示する機能を実装します。
現状の問題点
今の段階では、1+1=の結果が、
"2.0" (シンプルに "2" でいいんじゃない?)
また、10÷6のように割り切れない計算をすると
桁数が非常に多くなってしまううえ、
"1.6666666666666667"
というふうに、最後が謎の7になっています。
これはコンピューター上の仕様のようですが、
一般的には、「6が永遠と続く」という認識なので、
ユーザーからしたら不具合かと思われかねません。
そこで、一般的な電卓に習い、12桁までの表示にするとか、
小数点以下n位までの表示にする、
といった機能を実装していきます。
一般電卓の多くは、「小数点セレクター」「ラウンドセレクター」
という機能があり、
「小数点セレクター」は、小数点以下第何位まで表示するか、
「ラウンドセレクター」は、小数点セレクターで設定した位置に丸める際、
切り上げか、切捨てか、四捨五入するかなどを設定できる機能です。
カシオ計算機のサイトなどで使い方が詳しく載っています。
今回の実装ではこれらの機能をお手本にしているので、
理解度を高めるためにも、一度ご覧になることをオススメします。
自作のRoundSelectorクラス
Calcから送られてきた文字列を、成型した文字列に変換するクラスです。
引数に、計算結果のdouble、小数点の位置、丸めの方法を定数で指定します。
テキストビューにセットする前にフィルターを挟むように使います。
静的メソッドとして定義しました。
public class RoundSelector { public static final int POINT_5 = 5,POINT_4 = 4,POINT_3 = 3,POINT_2 = 2,POINT_1 = 1,POINT_0 = 0; public static final int ROUND_F = 10,ROUND_CUT = 11,ROUND_UP = 12,ROUND_5_4 = 14; public static String conversion(double value, int point, int round){ String string; BigDecimal bd = new BigDecimal(value); int mode = 0; switch (round){ case ROUND_F: return bd.toString(); case ROUND_CUT: mode = BigDecimal.ROUND_DOWN; break; case ROUND_UP: mode = BigDecimal.ROUND_UP; break; case ROUND_5_4: mode = BigDecimal.ROUND_HALF_UP; break; } BigDecimal bigDecimal = bd.setScale(point,mode); string = bigDecimal.toString(); Log.d("hogehoge","bd =" + bigDecimal.toString() ); return string; } public static String conversion(String value,int point,int round){ return conversion(Double.parseDouble(value),point,round); } public static String formatBasic(String string){ DecimalFormat df1 = new DecimalFormat("#,##0.############"); return df1.format(Double.valueOf(string)); } }
メインアクティビティの、Calcからのコールバックで送られてくる文字列に対して、
RoundSelectorを適用します。
calc = new Calc(); calc.setListener(new Calc.Callback() { @Override public void onTextChanged(String string) { displayView.setText(string); Log.d("hoge", RoundSelector.conversion(string,0,RoundSelector.ROUND_CUT)); Log.d("hoge", RoundSelector.conversion(string,3,RoundSelector.ROUND_CUT)); Log.d("hoge", RoundSelector.conversion(string,5,RoundSelector.ROUND_5_4)); Log.d("hoge", RoundSelector.conversion(string,3,RoundSelector.ROUND_F)); } });
10÷6は、以下のような結果となります。
D/hoge: 1
D/hoge: 1.666
D/hoge: 1.66667
D/hoge: 1.6666666666666667406815349750104360282421112060546875
ただし、現段階ではコールバックで送られてくるテキスト全てに適用しているので、
ユーザーが少数を入力した際も丸められてしまいます。
テキストが、入力中なのか、計算の答えとして送られてきたものなのか、
判別する処理が必要です。
私の場合は、State.getStateValue()で得られる定数がSTATE_D(答えを表示している状態)
であれば数値の文字列を成型するように修正しましたが、
もっといいやり方もあると思うので、
独自の実装をしてみてください。
端数処理方法の設定として、
・小数点以下の桁数
・丸める方法
の定数を、SharedPreferencesに保存しておくと、
ユーザーの使用環境に合わせた、
利便性の高い電卓にすることができます。