虽然现在我们日常生活中很少用到计算器,但在一些数学题或者物理题目上还是非常有帮助的,所以我就想在Android Studio上做一个计算器
grid layout的一些使用属性
android:id="@+id/gridlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0F0F0"
android:alignmentMode="alignBounds"
android:rowCount="9"
android:columnCount="4"
android:orientation="horizontal"
tools:context=".MainActivity"
tools:ignore="GridLayout">
接着是计算器的各个按钮
android:id="@+id/edit"
android:layout_gravity="right|bottom"
android:text="0"
android:textSize="35dp"
android:layout_columnSpan="4"
android:layout_rowWeight="2"
android:layout_columnWeight="1"
android:background="@null"/>
android:id="@+id/view"
android:layout_gravity="right|bottom"
android:text="0"
android:textSize="55dp"
android:layout_columnSpan="4"
android:layout_rowWeight="2"
android:layout_columnWeight="1"/>
然后我们开一下呈现出来的图是什么样子的(如下)
到这里我们就完成了1/3的工程,紧接着是让各个数字符号对应到各个按钮
参考原文博客连接部分运用的是FindViewByMe(XML)这个插件,连接按钮变得十分方便。建立按钮后,如果每个都要单独设置监听事件会十分麻烦,所以有一个方法onClick方法,多个按钮一起监听。但是在使用此方法是必须连接View.OnClickListener接口。然后set后即可使用。
首先建立按钮(这只是单单的建议按钮,连接按钮的代码在底下)
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private GridLayout gridlayout;
private EditText edit;
private TextView view;
private Button add;
private Button substact;
private Button multiply;
private Button divide;
private Button seven;
private Button eight;
private Button nine;
private Button left;
private Button four;
private Button five;
private Button six;
private Button right;
private Button three;
private Button two;
private Button one;
private Button Clean;
private Button dot;
private Button zero;
private Button equal;
}
然后把每个按钮和对应的数字符号对应起来
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridlayout = (GridLayout) findViewById(R.id.gridlayout);
edit = (EditText) findViewById(R.id.edit);
view = (TextView) findViewById(R.id.view);
add = (Button) findViewById(R.id.add);
substact = (Button) findViewById(R.id.substact);
multiply = (Button) findViewById(R.id.multiply);
divide = (Button) findViewById(R.id.divide);
seven = (Button) findViewById(R.id.seven);
eight = (Button) findViewById(R.id.eight);
nine = (Button) findViewById(R.id.nine);
left = (Button) findViewById(R.id.left);
four = (Button) findViewById(R.id.four);
five = (Button) findViewById(R.id.five);
six = (Button) findViewById(R.id.six);
right = (Button) findViewById(R.id.right);
three = (Button) findViewById(R.id.three);
two = (Button) findViewById(R.id.two);
one = (Button) findViewById(R.id.one);
Clean = (Button) findViewById(R.id.Clean);
dot = (Button) findViewById(R.id.dot);
zero = (Button) findViewById(R.id.zero);
equal = (Button) findViewById(R.id.equal);
edit.setOnClickListener(this);
view.setOnClickListener(this);
add.setOnClickListener(this);
multiply.setOnClickListener(this);
divide.setOnClickListener(this);
dot.setOnClickListener(this);
one.setOnClickListener(this);
two.setOnClickListener(this);
three.setOnClickListener(this);
four.setOnClickListener(this);
five.setOnClickListener(this);
six.setOnClickListener(this);
seven.setOnClickListener(this);
eight.setOnClickListener(this);
nine.setOnClickListener(this);
zero.setOnClickListener(this);
right.setOnClickListener(this);
Clean.setOnClickListener(this);
left.setOnClickListener(this);
equal.setOnClickListener(this);
substact.setOnClickListener(this);
}
记录上一个结果
private String lastresult;
判断当前是否进行计算
private boolean now;
点击按钮后会输出相对应的数字和符号(onClick)
@Override
public void onClick(View v) {
String text = edit.getText().toString();//获取当前文本编译框内容
String lasttext;
boolean clean = false;
Formulautil a = new Formulautil();
if (text.equals("0"))
{
edit.setText("");
}
switch(v.getId())
{
case R.id.zero:
edit.setText(edit.getText() + "0");
Clean.setText("C");
now = false;
break;
case R.id.one:
edit.setText(edit.getText() + "1");
Clean.setText("C");
now = false;
break;
case R.id.two:
edit.setText(edit.getText() + "2");
Clean.setText("C");
now = false;
break;
case R.id.three:
edit.setText(edit.getText() + "3");
Clean.setText("C");
now = false;
break;
case R.id.four:
edit.setText(edit.getText() + "4");
Clean.setText("C");
now = false;
break;
case R.id.five:
edit.setText(edit.getText() + "5");
Clean.setText("C");
now = false;
break;
case R.id.six:
edit.setText(edit.getText() + "6");
Clean.setText("C");
now = false;
break;
case R.id.seven:
edit.setText(edit.getText() + "7");
Clean.setText("C");
now = false;
break;
case R.id.eight:
edit.setText(edit.getText() + "8");
Clean.setText("C");
now = false;
break;
case R.id.nine:
edit.setText(edit.getText() + "9");
Clean.setText("C");
now = false;
break;
case R.id.dot:
edit.setText(edit.getText() + ".");
Clean.setText("C");
now = false;
break;
case R.id.right:
edit.setText(edit.getText() + ")");
Clean.setText("C");
now = false;
break;
case R.id.left:
edit.setText(edit.getText() + "(");
Clean.setText("C");
now = false;
break;
case R.id.add:
edit.setText(edit.getText() + "+");
Clean.setText("C");
now = false;
break;
case R.id.substact:
edit.setText(edit.getText() + "-");
Clean.setText("C");
now = false;
break;
case R.id.multiply:
edit.setText(edit.getText() + "×");
Clean.setText("C");
now = false;
break;
case R.id.divide:
edit.setText(edit.getText() + "÷");
Clean.setText("C");
now = false;
break;
case R.id.equal:
edit.setText(edit.getText() + "=");
lasttext = edit.getText().toString();
String a1 = String.valueOf(a.caculate(lasttext));
view.setText(a1);
break;
//清楚操作,保留上一结果,引入计算部分
case R.id.Clean:
edit.setText("0");
Clean.setText("C");
now = true;
//归零操作,不保留上一次结果
}
}
完成了连接部分,就是最核心的计算部分
import java.util.Stack;
import java.math.BigDecimal;
public class Formulautil {
/**大致思路是利用栈的出栈入栈压栈来处理一个运算式的先后级排序,进行相映的运算.*/
//数字栈:用于存储表达式中的各个数字
private Stack numberStack = null;
//符号栈:用于存储运算符和括号
private Stack symbolStack = null;
private int scale;//除法时出现循环小数保留精度
public Formulautil(int scale) {
super();
this.scale = scale;
}
public Formulautil() {
this(32);
}
/**从外面把字符串传递进来!!!*/
public BigDecimal caculate(String numStr) {
//判断算数表示是否结束,也就是判断结尾有木有=号!没有给加上!
//equals方法:值的比较
//charAt方法:检索方法
if (numStr.length() > 1
&& !"=".equals(numStr.charAt(numStr.length() - 1) + "")) {
numStr += "=";
}
//检查表达式是否是正确的!利用Standard方法(自定义)
if (!isStandard(numStr)) {
String isstandardtext;
isstandardtext = "出错";
return null;
}
// 初始化栈
if (numberStack == null) {
numberStack = new Stack();
}
numberStack.clear();
if (symbolStack == null) {
symbolStack = new Stack();
}
symbolStack.clear();
/**!!!!!!!!!!核 心!!!!!!!!!!!!*/
//创建一个StringBuffer,用来放多位的数字
StringBuffer temp = new StringBuffer();
// 从表达式的第一个字符开始处理
for (int i = 0; i < numStr.length(); i++) {
// 获取一个字符
char ch = numStr.charAt(i);
// 若当前字符是数字
if (isNumber(ch)) {
// 加入到数字缓存中
temp.append(ch);
} else { // 非数字的情况
// 将数字缓存转为字符串
String tempStr = temp.toString();
if (!tempStr.isEmpty()) {
BigDecimal num = new BigDecimal(tempStr);
// 将数字压栈
numberStack.push(num);
// 重置数字缓存
temp = new StringBuffer();
}
// 判断运算符的优先级,若当前优先级低于栈顶的优先级,则先把计算前面计算出来
while (!comparePri(ch) && !symbolStack.empty()) {
// 出栈,取出数字,后进先出
BigDecimal b = numberStack.pop();
BigDecimal a = numberStack.pop();
// 取出运算符进行相应运算,并把结果压栈进行下一次运算
switch ((char) symbolStack.pop()) {
case '+':
numberStack.push(a.add(b));
break;
case '-':
numberStack.push(a.subtract(b));
break;
case '×':
numberStack.push(a.multiply(b));
break;
case '÷':
try {
numberStack.push(a.divide(b));
} catch (java.lang.ArithmeticException e) {
// 进行除法出现无限循环小数时,就会抛异常,此处设置精度重新计算
numberStack.push(a.divide(b, this.scale,
BigDecimal.ROUND_HALF_EVEN));
}
break;
default:
break;
}
} // while循环结束
if (ch != '=') {
// 符号入栈
symbolStack.push(new Character(ch));
// 去括号
if (ch == ')') {
symbolStack.pop();
symbolStack.pop();
}
}
}
} // for循环结束
// 返回计算结果
return numberStack.pop();
}
/**=================================检查算数表达式是否合格======================================*/
private boolean isStandard(String numStr) {
// 表达式不能为空
if (numStr == null || numStr.isEmpty())
return false;
// 用来保存括号,检查左右括号是否匹配
Stack stack = new Stack();
// 用来标记'='符号是否存在多个
boolean b = false;
for (int i = 0; i < numStr.length(); i++) {
char n = numStr.charAt(i);
// 判断字符是否合法
if (!(isNumber(n) || "(".equals(n + "") || ")".equals(n + "")
|| "+".equals(n + "") || "-".equals(n + "")
|| "×".equals(n + "") || "÷".equals(n + "") || "=".equals(n
+ ""))) {
return false;
}
// 将左括号压栈,用来给后面的右括号进行匹配
if ("(".equals(n + "")) {
stack.push(n);
}
if (")".equals(n + "")) { // 匹配括号
if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) // 括号是否匹配
return false;
}
// 检查是否有多个'='号
if ("=".equals(n + "")) {
if (b)
return false;
b = true;
}
}
// 可能会有缺少右括号的情况
if (!stack.isEmpty())
return false;
// 检查'='号是否不在末尾
if (!("=".equals(numStr.charAt(numStr.length() - 1) + "")))
return false;
return true;
}
/**=================================判断是否是0-9的数字========================================*/
private boolean isNumber(char num) {
if ((num >= '0' && num <= '9') || num == '.')
return true;
return false;
}
/**==============比较优先级,如果当前运算符比栈顶元素运算符优先级高则返回true,否则返回false==========*/
private boolean comparePri(char symbol) {
// 空栈返回ture
if (symbolStack.empty()) {
return true;
}
/*
我设计得这个计算器加减乘除,lg,ln,括号,三角函数,正常得优先级就是有括号先算括号,然后再乘除,在加减
第一级:(
第二级: × ÷ sin cos tan lg ln
第三级: + -
第四级:)
*/
// 查看堆栈顶部的对象
char top = (char) symbolStack.peek();
if (top == '(') {
return true;
}
// 比较优先级
switch (symbol) {
case '(': // 优先级最高
return true;
// 优先级比'+'和'-'高
case '×': {
if (top == '+' || top == '-')
return true;
else
return false;
}
// 优先级比'+'和'-'高
case '÷':
if (top == '+' || top == '-')
return true;
else
return false;
case '+':
return false;
case '-':
return false;
// 优先级最低
case ')':
return false;
// 结束符
case '=':
return false;
default:
break;
}
return true;
}
}
然后我们看看运行的结果
加法
减法
乘法
除法
有小数点的数字的加减乘除也可以运行
有一个地方就是EditText那里可以加上这么一句话
android:background="@null"
这样你的EditText就不会底下出现一条横线,看着比较舒适
参考链接:
https://github.com/bestxiaoxiaoming-hm/AndroidStudio----java-
以上就是一个Android Studio制作的简单计算器
作者:周楷津
原文链接:https://blog.csdn.net/HeimuZ/article/details/106716141