最终计算器的掩饰效果,欢迎大家来找BUG.

http://codepen.io/lvanboy/full/LxKVxJ/

功能:

1.按照运算符的优先级运算

2.利用上次的结果继续运算

3.多个数字混合运算

1、将一个中序表达式转化成为逆波兰表达式

首先维护的是两个栈,我们这里暂且称为S1和S2,S1中的结果最后存的就是逆波兰表达式,S2中将用于暂时存放运算符并且在最终形成逆波兰表达式的时候,该栈是会清空的。下面我们看看怎样具体的形成逆波兰表达式。

在此首先定义一下运算符的优先级关系,从小到达排序,相同优先级没有用逗号隔开:(,+-,*\,负号,)。

从左至右遍历一个给定的中序表达式,也就是我们常规的数学计算的表达式。

(1)** 如果遇到的是数字,我们直接加入到栈S1中;**

(2)** 如果遇到的是左括号,则直接将该左括号加入到栈S2中;**

(3)** 如果遇到的是右括号,那么将栈S2中的运算符一次出栈加入到栈S1中,直到遇到左括号,但是该左括号出栈S2并不加入到栈S1中;**

(4)** 如果遇到的是运算符,包括单目运算符和双目运算符,我们按照下面的规则进行操作:**

如果此时栈S2为空,则直接将运算符加入到栈S2中;

如果此时栈S2不为空,当前遍历的运算符的优先级大于等于栈顶运算符的优先级,那么直接入栈S2;

如果此时栈S2不为空,当前遍历的运算符的优先级小于栈顶运算符的优先级,则将栈顶运算符一直出栈加入到栈S1中,直到栈为空或者遇到一个运算符的优先级小于等于当前遍历的运算符的优先级,此时将该运算符加入到栈S2中;

(5)** 直到遍历完整个中序表达式之后,栈S2中仍然存在运算符,那么将这些运算符依次出栈加入到栈S1中,直到栈为空。**

按照上面的五条操作反复进行完成,那么栈S1中存放的就是逆波兰表达式。

2、利用逆波兰表达式求值

利用逆波兰表达式求计算式的值其实很简单,正式因为这一点,所以逆波兰表达式才在编译原理中被用于计算一个表达式的值。

下面来具体看看如何求一个逆波兰表达式的值:

我们此时维护一个数据结果栈S3,我们将会看到该栈中最后存放的是最终的表达式的值。我们从左至右的遍历栈S1,然后按照下面的规则进行操作栈S3.

(1)** 如果遇到的是数字,那么直接将数字压入到S3中;**

(2) ** 如果遇到的是单目运算符,那么取S3栈顶的一个元素进行单目运算之后,将结果再次压入到栈S3中;**

(3)** 如果遇到的是双目运算符,那么取S3栈顶的两个元素进行,首先出栈的在左,后出栈的在右进行双目运算符的计算,将结果再次压入到S3中。**

按照上面的三个规则,遍历完整个栈S1,那么最后S3中的值就是逆波兰表达式的值了,所以我们可以看出来使用逆波兰表达式进行求值是很简单的,只有两种操作要么是直接压栈,要么是运算之后将结果压栈。

3、JavaScript 具体实现代码,为了方便dom操作引用了jQuery

HTML 结构是这样的:样式大家自己发挥

calculator

Calculator

下面是参考代码:这里独立实现了AC,Ans,CE(在原先的算法实现)

$(function(){

var nums = ["AC","CE","%","/",

"7","8","9","*","4","5","6","-",

"1","2","3","+",".","0","Ans","="];

//利用数组模拟堆栈,新建两个堆栈

//s1 的结果 存放的是 逆波兰表达式,

//s2 暂时存放运算符

var s1 = [] ,s2 = [];

// 定义运算符 优先级 ,

var signPriority = [["+","-"],["*","/","%"],["-","."]];

// 定义数字正则

var reg = /\d+/;

// 单目规则

var regSingle = /[\-\.]/;

// 不可显示字符

var hidden = /[AC=CE=Ans]/;

// 连接显示数字

var concatNum="";

// 保存结果

var s3 = [],result;

//连接计算数字

var sum ="";

//计CE的次数

var count = 0;

//迭代元素

var key = $("#nums").children();

key.each(function(index,val){

//写入计算器按钮的值

$(val).text(nums[index]);

//实现的按钮动态效果

$(val).on("mousedown",function(e){

$(this).css({"box-shadow":"-1px -1px 3px #666"})

})

$(val).on("mouseup",function(e){

$(this).css({"box-shadow":"2px 2px 3px #555"})

})

$(val).on("click",function(e){

//显示字符

if(!hidden.test($(this).text())){

concatNum += $(this).text();

$("#output").text(concatNum);

}

//如果是数字,拼接数字

if(reg.test($(this).text())){

sum += $(this).text();

}else{

s1.push(parseInt(sum));

sum =" ";

//Ans 保存上一次的值,不显示该值

if($(this).text()=="Ans"){

s1.push(s3[0]);

s3 = [];

}else{

s3 = [];

}

//AC功能清空屏幕,不显示该键值

if($(this).text()=="AC"){

$("#output").text("");

concatNum="";

s1 = [];

s2 = [];

s3 = [];

}

//CE清除一个值,不显示该值

if($(this).text()=="CE"){

concatNum = concatNum.substr(0,concatNum.length-1);

// s1.pop();

count++;

s1[s1.length-count]=parseInt(concatNum);

$("#output").text(concatNum);

}

//如果s2 为空,直接将运算符压入s2中

if(s2.length==0){

s2.push($(this).text());

}else{

//如果s2不为空,判断运算符优先级

var sTopElem = s2[s2.length-1];

var curElem = $(this).text();

//如果当前优先级大于栈顶优先级,直接入s2

if(judgePriority(curElem,sTopElem)){

s2.push(curElem);

}else{

//堆栈不为空,当前元素不小于栈顶元素优先级,一直从s2出栈到s1

while(!judgePriority(curElem,sTopElem)&&s2.length!==0){

s1.push(s2.pop());

}

//不满足上面条件,再把当前符号入栈s2

s2.push($(this).text());

}

}

}

//计算逆波兰堆栈

if($(this).text()=="="){

var tem = [];

//清空链接字符

concatNum="";

//清空符号

s2 = [];

//清空计数器

count = 0;

//遍历s1

for(var i=0;i

//如果当前为数字,直接入栈s3

if(reg.test(s1[i])){

s3.push(parseFloat(s1[i]));

}

//单目运算

else if(regSingle.test(s1[i])){

if(s1[i]=="-"){

s3.push(-s3.pop());

}

if(s1[i]=="."){

s3[s3.length-2]=(s3.pop()/10);

}

}else{ //双目运算

if(s1[i]=="+"){

s3.push(parseFloat(s3.pop())+parseFloat(s3.pop()));

}

if(s1[i]=="-"){

s3.push(parseFloat(s3.pop())-parseFloat(s3.pop()));

}

if(s1[i]=="*"){

s3.push(parseFloat(s3.pop())*parseFloat(s3.pop()));

}

if(s1[i]=="/"){

s3.push(parseFloat(s3.pop())/parseFloat(s3.pop()));

}

if(s1[i]=="%"){

s3.push(parseFloat(s3.pop())%parseFloat(s3.pop()));

}

}

}

//清空逆波兰

s1=[];

//最终结果s3

if(s3.length==1){

//判断结果是否非法

if(isNaN(s3[0])){

$("#output").text("非法操作");

s3 = [];

}else{

$("#output").text(s3[0]);

}

}else{

result=s3[0]+s3[1];

if(isNaN(result)){

$("#output").text("非法操作");

s3 = [];

}else{

$("#output").text(result);

}

}

}

})

//判断当前运算符与栈顶运算符优先级

function judgePriority(sign1,sign2){

var index1,index2;

for(var i=signPriority.length-1;i>=0;i--){

for(var j=signPriority[i].length-1;j>=0;j--){

if(sign1==signPriority[i][j]){

index1=i;

}

if(sign2==signPriority[i][j]){

index2=i;

}

}

}

if(index1>index2){

return true;

}else{

return false;

}

};

})

})

逆波兰计算器android源码简书,计算器的核心算法-JavaScript实现(逆波兰表达式)...相关推荐

  1. 逆波兰计算器android源码简书,汪都能理解的逆波兰计算器(C++实现)

    简介 EXPLANATION 逆波兰表示法(Reverse Polish notation, RPN)也称作后缀表示法,与之对应的是波兰表示法(Polish notation),也就是前缀表示法.之所 ...

  2. Android源码和内核源码的下载,编译和执行

    笔者依据罗升阳老师的<Android 系统源码情景分析>一书,尝试下载,编译和执行Android源码和内核源码.但可能是软件源"被墙"或版本号更新的原因.期间遇到诸多问 ...

  3. android源码编译 简书,android学习笔记之源码编译

    编译环境 1.需要Ubuntu 64bit,建议Ubuntu14.04 64-bit 2.安装openJDK7 $ sudo apt-get update $ sudo apt-get install ...

  4. [Android源码]Android源码之高仿飞鸽传书WIFI热点搜索与创建(一)

    (本文详情来源:android源码 http://www.eoeandroid.com/thread-296427-1-1.html   转载请注明出处!)  [Android源码分享]飞鸽传书的An ...

  5. 体验Android:个人所得税计算器 含源码

    体验Android 个人所得税计算器 含源码 http://files.cnblogs.com/mobile/ptc.rar 转载于:https://www.cnblogs.com/mobile/ar ...

  6. 【Android项目】本地FM收音机开发及源码简析

    [Android项目]本地FM收音机开发及源码简析 目录 1.概述 2.收音机的基本原理 3.收音机其他信息 RDS功能 4.Android开发FM收音机源码解析 5.App层如何设计本地FM应用 6 ...

  7. 简诉android源代码编译过程,详解Android源码的编译

    在这里我们将介绍的是Android源码的编译,主要基于Android 1.0环境下.希望对大家有所帮助. 本文将为大家介绍的是如何设置Android源码的编译环境,包括Linux下的配置.主要基于An ...

  8. [转]2014年最新810多套android源码2.46GB免费一次性打包下载

    转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...

  9. 转--2014年最新810多套android源码2.46GB免费一次性打包下载

    转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...

最新文章

  1. “敏捷版”全链路压测
  2. 写一个“特殊”的查询构造器 - (四、条件查询:复杂条件)
  3. 在Java项目中整合Scala
  4. Spark生态圈及安装
  5. 1688商品类目API接口-(item_cat_get-获得1688商品类目接口)
  6. OC 5217欧创芯原装芯片一款连续电感电流导通模 式的降压型 LED 恒流驱动器,SOT23-5 封装
  7. linux网络操作系统-实训项目的实现
  8. 多模光纤与单模光纤熔接及用哪种光模块的问题。
  9. Xtool X100 PAD2 Error Code 5 Data Not Exist Solution
  10. vue中的路由跳转和传参
  11. chrome五十大实用插件集合
  12. 苹果电脑MacBook插入移动硬盘没有反应/不显示
  13. while循环和doWhile循环
  14. 语音识别相关会议期刊、资料、主页博客
  15. VMware16安装过程分享
  16. 路遥《平凡的世界》经典哲语
  17. 摄影大师2020,10款PS扩展插件合集
  18. 集成学习与模型融合(kaggle-Elo Merchant Category Recommendation)
  19. Centos7 安装向日葵(最新版本)
  20. 合肥工业大学机器人足球仿真robcup作业二(python实现)附代码有注释

热门文章

  1. CASE_04 基于FPGA的电梯控制器
  2. TIMING_06 VIVADO环境下的时序约束 之 输入延迟约束
  3. oracle10g优化器默认,Oracle10g数据库优化实用心得小结
  4. mysql 文件组织_数据库如何组织数据?
  5. 五年级用计算机探究规律教案,人教版五年级上册数学《用计算器探索规律》教案...
  6. java工具类下载_java文件下载工具类
  7. linux 网络服务器 源码下载,linux下 各类tcp网络服务器的实现源代码.doc
  8. 大文本存mysql怎么建索引_如何正确合理的建立MYSQL数据库索引
  9. oracle 赋值到cmd,CMD操作oracle数据导库过程图解
  10. nacos 公共_SpringCloud配合注册中心Nacos的使用