1.先看看界面,有点像原生Android的计算器(我写的没那么好,在这里膜拜一下~)

Android表达式计算器_第1张图片

Android表达式计算器_第2张图片

Android表达式计算器_第3张图片

Android表达式计算器_第4张图片

我写的这个表达式计算器似乎与Android原生的计算器有点像,实际上这个计算器比那个在实现上要简单,但是功能方面都类似。(原生的计算器的三角函数计算只实现了弧度计算,这里弧度和角度都实现了)

 

2.思路:表达式计算

之前用CC++写过一个表达式计算的程序(看这里),这里用Java重新实现,思路都是一样的:

2.1预处理,将表达式转化为栈结构。

// 将一个表达式转化为栈结构public ExStack getInfxStackfromStr(String infx) {// 新建一个栈存储表达式ExStack myStack = new ExStack();// 做一个标记(是否获得了一个数字)// 如果为假,将‘-’看做数字的一部分,为真,将‘-’看做运算符boolean getANum = false;// 临时字符串StringBuffer temStr = new StringBuffer();char temChar = ' ';// 如果表达式以'-('开头,自动插入0if (infx.length() > 2 && '-' == infx.charAt(0) && '(' == infx.charAt(1)) {myStack.push("0");}for (int i = 0; i < infx.length(); i++) {temChar = infx.charAt(i);if ((!getANum && '-' == temChar) || !isOperator(temChar)) // 是数字{temStr.append(temChar);getANum = true;} else { // 是一个操作符if (!"".equals(temStr.toString())) {myStack.push(temStr.toString());// 压栈temStr.delete(0, temStr.length()); // 清空temStr}myStack.push("" + temChar); // 压入运算符if (')' != temChar) {getANum = false;} else { // ‘)’好后面的‘-’好应被看做运算符getANum = true;}}}if (0 != temStr.length()) {myStack.push(temStr.toString());}return myStack;}

2.2最关键的部分:将中缀表达式转化为后缀表达式

public ExStack infixToPosfix(ExStack infixStack) {String[] exps = infixStack.getDataArray();ExStack myPosfixStack = new ExStack();ExStack temStack = new ExStack();boolean getNumber = false;boolean getOperator = false;for (int i = 0; i < infixStack.size(); i++) // 注意遍历区间控制!warrning!{if (isNumStr(exps[i])) // 是数字,直接放入posfix序列中{getOperator = false;if (getNumber) // 如果之前处理的也是数字,在它后面插入一个*号{myPosfixStack.push(exps[i]);myPosfixStack.push("*");} else {myPosfixStack.push(exps[i]);getNumber = true;}} else if ("(".equals(exps[i])) // 遇到开括号,压栈{temStack.push(exps[i]);} else if (")".equals(exps[i])) // 遇到闭括号时{if (temStack.isEmpty()) {LogInfo.printError("brackets not match!");return null;} else {while (!"(".equals(temStack.top())) {myPosfixStack.push(temStack.top());temStack.pop();if (temStack.isEmpty()) {LogInfo.printError("brackets not match!");return null;}}if ("(".equals(temStack.top())) {temStack.pop(); // 弹出开括号}}} else if (isOperatorStr(exps[i])) // 为运算符{getNumber = false;if (getOperator) // 连续两个运算符{LogInfo.printError("Wrong Exps.");return null;} else {getOperator = true;}while (!temStack.isEmpty()&& !"(".equals(temStack.top())&& compareCaculatorOperator(temStack.top(), exps[i]) > 0) {myPosfixStack.push(temStack.top());temStack.pop();}temStack.push(exps[i]); // 将输入运算符放入栈内}}while (!temStack.isEmpty()) {if ("(".equals(temStack.top())) {LogInfo.printError("brackets not match!");return null;}myPosfixStack.push(temStack.top());temStack.pop();}return myPosfixStack;}

2.3计算后缀表达式的值

public String caculate(ExStack posfix) {if (null == posfix) {LogInfo.printError("posfix stack is Empty!");return errorInfo;}String[] posfixStr = posfix.getDataArray();ExStack caculateStack = new ExStack();double num1 = 0.;double num2 = 0.;for (int i = 0; i < posfix.size(); i++) {if (isNumStr(posfixStr[i])) { // 如果是数字,进行压栈caculateStack.push(posfixStr[i]);} else if (isOperatorStr(posfixStr[i])) { // 如果是运算符,取出数字,进行计算if (caculateStack.size() < 2) // 如果栈中数字数目小于2,报错{LogInfo.printError("Wrong Posfix Exps:");LogInfo.printExStack("posfix", posfix);return errorInfo;}try {if ("+".equals(posfixStr[i])) {num1 = Double.parseDouble(caculateStack.top());caculateStack.pop();num2 = Double.parseDouble(caculateStack.top());caculateStack.pop();caculateStack.push(Double.toString(num2 + num1));} else if ("-".equals(posfixStr[i])) {num1 = Double.parseDouble(caculateStack.top());caculateStack.pop();num2 = Double.parseDouble(caculateStack.top());caculateStack.pop();caculateStack.push(Double.toString(num2 - num1));} else if ("*".equals(posfixStr[i])) {num1 = Double.parseDouble(caculateStack.top());caculateStack.pop();num2 = Double.parseDouble(caculateStack.top());caculateStack.pop();caculateStack.push(Double.toString(num2 * num1));} else if ("/".equals(posfixStr[i])) {num1 = Double.parseDouble(caculateStack.top());caculateStack.pop();num2 = Double.parseDouble(caculateStack.top());caculateStack.pop();if (Math.abs(num1) < 1e-10 && Math.abs(num2) < 1e-10) {LogInfo.printInfo("Both divide number and dividend number are zero.");return naNInf;} else if (Math.abs(num1) < 1e-10) {LogInfo.printInfo(" Dividend number is zero.");return infinityInfo;}caculateStack.push(Double.toString(num2 / num1));} else if ("^".equals(posfixStr[i])) {num1 = Double.parseDouble(caculateStack.top());caculateStack.pop();num2 = Double.parseDouble(caculateStack.top());caculateStack.pop();caculateStack.push(Double.toString(Math.pow(num2, num1)));} else {LogInfo.printError("Unknow caculator operator:"+ posfixStr[i]);return errorInfo;}} catch (NumberFormatException e) {LogInfo.printError("NumberFormatException:" + e.toString());return errorInfo;}}}if (1 == caculateStack.size()) {return caculateStack.top();} else {LogInfo.printError("Unknow Error:");LogInfo.printExStack("caculateStack:", caculateStack);return errorInfo;}}

3.高级运算例如三角函数的实现

表达式计算只能够处理+-*/以及左右括号,而不能处理例如LogExp等运算,这里是这么处理的。

在点击Log或者Sin等按钮后,所做的事情是,查找编辑框中表达式最后一个元素是不是数字,如果是则计算Log(数字),然后将计算结果替换这个数字,同时在上方的小标签(TextView)中,给出这样的提示,Log(数字)=结果,用户就知道发生了什么。这样编辑框中的内容仅仅是表达式计算所能处理的中缀表达式,在用户按下等号后计算这个表达式的值。这种计算方式,对于几乎所有能支持的表达式都是可以计算的,只是可能要分好几步。

 

android原生的计算器,是这么处理的,它将高级计算的运算也加入到表达式中,比如SinCos等,直到用户点击等号,最后来计算这个表达式的最终结果。这可能就需要编译原理里面文法的知识了。(对于原生的计算器,我还没搞大明白。。。)

 

4.计算器啊计算器

其实除了基本的运算逻辑,一个计算器要考虑的还有很多,比如精确度、四舍五入、如何避免错误的括号匹配,如何避免用户在一个数字内输入多个小数点,如何避免用户输入错误的表达式,对于语法错误的表达式怎么尽量矫正等等,其实很繁琐的。

 

5.一个问题

由于面板上按钮比较多,所以分了两屏,用HorizontalScrollView实现的。问题是怎么能让这个HorizontalScrollView只显示左屏或者右屏,而不出现那种左屏显示一部分右屏显示一部分的状况?

我的尝试

// 自动滚动(未实现)private void autoScroll() {int x = horizontal_scrollview.getScrollX();LogInfo.printInfo("scrollx:" + x);if (x > 320 / 2)horizontal_scrollview.smoothScrollBy(320, 0);else {horizontal_scrollview.smoothScrollBy(0, 0);}}

我想让x的值大于160时,滚到右边,小于160时滚到最左边,我看了一个网上的demo,用smoothScrollBy是可以的,但是这里没效果,最终还没解决。

不知哪位大侠能否指点一下,3Q~


工程源码:

http://download.csdn.net/detail/he_qiao_2010/5997973

没有积分的可以到这里下载:

http://pan.baidu.com/share/link?shareid=413973185&uk=1158831200


APK文件:

http://pan.baidu.com/share/link?shareid=4121195332&uk=1158831200


更多相关文章

  1. Android 带百分比数字的水平、圆形进度条
  2. Android中判断字符串中必须包含字母或者数字_Android
  3. Android 计算器编程实现
  4. Android Studio 启用Lambda表达式
  5. Android数字证书
  6. Android 数字版权保护播放器开发
  7. Android计算器简单逻辑实现
  8. 【安卓开发】UI设计基础4:用网格布局 GridLayout 实现计算器UI
  9. Android平台上的计算器APP(付源码)

随机推荐

  1. Android(安卓)消息传递机制分析
  2. Android 以widget的方式集成Dcloud h5+SD
  3. Android系统升级全流程
  4. Android支持的视频格式
  5. android主流UI布局
  6. [置顶] 超赞!!Android视图讲解!!以及Andr
  7. Android(安卓)Junit单元测试
  8. Android arm linux kernel启动流程(一)
  9. 探究android:largeHeap
  10. Debug Android and Linux suspend and re