JS实现轻量级计算器
想尝试做一个网页版计算器后,参考了很多博客大神的代码,综合归纳、总结修改,整理如下文。
一、HTML+CSS
具体结构样式如下图,基本参照手机计算器界面。按钮功能可以查看demo,都可以实现。
  
这部分布局不是重点,只附上代码以便理解JS行为。
HTML/结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS实现轻量级计算器</title>
<link href="css/style.css" type="text/css" rel="stylesheet" />
<script src="js/script.js" type="text/javascript" rel="stylesheet"></script>
</head>
<body>
<div id="box">
<div id="top">
<p>Lightweight Calculator by PYJ</p>
<input id="screen0" type="text" style="margin-top: 100px;" disabled/>
<input id="screen1" type="text" style="margin-top: 190px;" disabled/>
</div>
<div id="main">
<span class="div1" style="font-size: 26px">(</span>
<span class="div1" style="font-size: 26px">)</span>
<span class="div1" style="font-size: 26px">DEL</span>
<span class="div1">/</span> <span class="div2">7</span>
<span class="div2">8</span>
<span class="div2">9</span>
<span class="div1">*</span> <span class="div2">4</span>
<span class="div2">5</span>
<span class="div2">6</span>
<span class="div1">-</span> <span class="div2">1</span>
<span class="div2">2</span>
<span class="div2">3</span>
<span class="div1">+</span> <span class="div2">0</span>
<span class="div2">.</span>
<span class="div1">C</span>
<span class="div3" style="width: 94px;background: orangered;">=</span>
</div>
</div>
</body>
</html>
CSS/表现:
*{
    margin: 0;
    padding: 0;
    font-family: "Consolas", "Menlo", "Courier", monospace;
}
span{display: block;}
body{background: #f0f2f1;}
#box{
    width: 380px;
    height: 675px;
    margin-top: 8px;
    margin-left: auto;
    margin-right: auto;
    box-shadow:0 0 10px #888;
}
#top{
    width: inherit;
    height: 285px;
    background: #333333;
    position: relative;
}
#top p{
    color: #e7e7e7;
    font-size: 16px;
    padding-top: 5px;
    padding-right: 10px;
    text-align: right;
}
#top input{
    width: 368px;
    height: 70px;
    position: absolute;
    color: #e8e8e8;
    background: none;
    border: none;
    font-size: 35px;
    text-align: right;
    line-height: 70px;
    cursor: text;
    padding-right: 10px;
}
#main{
    width: inherit;
    height: 390px;
    background: #f0f2f1;
}
#main span{
    width: 94px;
    height: 77px;
    border-right: 1px solid #dff0d8;
    border-top: 1px solid #dff0d8;
    float: left;
    font-size: 32px;
    text-align: center;
    line-height: 80px;
    cursor: pointer;
}
.div1{color: orangered;}
.div2{color: #000;}
.div3{border-right: none;color: #fff;}
#main span:hover{background: #e1e1e1;}
#main span:active{box-shadow: 0 0 5px 5px #fff;}
二、JavaScript/行为
行为层要解决的问题大致可以总结为:获取被点击的按钮内容,给出相应反应或组成表达式;计算表达式并显示。
1. 初始化(清屏):
 window.onload = function(){
     var screen0 = document.getElementById('screen0'),   //获取上显示器内容
         screen1 = document.getElementById('screen1');   //获取下显示器内容
     screen0.value = null;
     screen1.value = null;
     calculate(screen0, screen1);
 };
2. 上面代码最后一行调用了calculate()函数,获取按钮字符:
 function calculate(screen0,screen1){
     var box = document.getElementById('main'), //获取按钮盒子
         count = 0;                             //记录显示器字符或数字个数
     box.onclick = function(e){
         var symbol = e.target.innerText;       //获取按钮字符
         //内容是否超过允许长度
         if((screen1.value + symbol).length > 40){
             alert('Content exceeds the maximum length!');
             return null;
         }
         if(symbol == 'C' ){          //清零
             count = 0;
             screen0.value = null;
             screen1.value = null;
         }else if(symbol != '='){     //表达式
             if(count == -1){         //对上一次计算的清空
                 screen0.value += "=" + screen1.value;
                 screen1.value = symbol;
                 count = 1;
             }else if(symbol == 'DEL'){
                 if(screen1.value == null){
                     count = 0;
                 }else{
                     screen1.value = screen1.value.slice(0,-1);
                     count--;
                 }
             }else{
                 screen1.value += symbol;
             }
         }else if(symbol == '='){    //计算结果
             screen0.value = screen1.value;
             screen1.value = test(screen1.value );
             count = -1;
         }
     }
 }
分别对清零、回删、“=”和其他字符情况做出判断,给予不同的处理结果。
3. 按了“=”,就表示要对前面的字符串进行计算了:
但在计算前,需要了解一下JS数字精度丢失的问题。计算机的二进制的实现和位数限制会使部分数无法有限表示,有穷的数在计算机的二进制里却是无穷的,因存储位数的限制而发生的“舍去”,就导致了精度的丢失。具体内容不再展开,可以去查看相关文档。
为了解决浮点数的精度丢失问题,在这里为Math对象定义了一个方法:
 Math.formatFloat = function (exp, digit){
     var m = Math.pow(10, digit);
     return parseInt(exp*m, 10)/m;
 };
     //把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数)
计算器最核心的算法就是表达式的运算。
本文的思想是,将表达式按符号拆分并运用递归:
 function test(text) {
     var index = 0;   //记录符号索引
     while(text){
         //首先计算括号内内容
         if(text.lastIndexOf("(") > -1){
             index = text.lastIndexOf("(");
             var endIndex = text.indexOf(")", index);
             if(endIndex > -1) {
                 var result = Math.formatFloat(test(text.substring(index + 1, endIndex)) ,2);
                 return Math.formatFloat(test(text.substring(0, index) + result + text.substring(endIndex + 1)) ,2);
             }
         }else if(text.indexOf("+") >-1){
             index = text.indexOf("+");
             return Math.formatFloat(test(text.substring(0, index)) + test(text.substring(index + 1)) ,2);
         }else if(text.lastIndexOf("-") > -1){
             index = text.lastIndexOf("-");
             if(text[index-1] == '*'){
                 return Math.formatFloat(test(text.substring(0, index-1)) * test(text.substring(index)) ,2);
             }else if(text[index-1] == '/'){
                 return Math.formatFloat(test(text.substring(0, index-1)) / test(text.substring(index)) ,2);
             }else{
                 return Math.formatFloat(test(text.substring(0, index)) - test(text.substring(index + 1)) ,2);
             }
         }else if(text.lastIndexOf("*") > -1){
                 index = text.lastIndexOf("*");
             return Math.formatFloat(test(text.substring(0, index)) * test(text.substring(index + 1)) ,2);
         }else if(text.lastIndexOf("/") > -1){
             index = text.lastIndexOf("/");
             return Math.formatFloat(test(text.substring(0, index)) / test(text.substring(index + 1)) ,2);
         }else{
             return Math.formatFloat(text,2);
         }
     }
     return null;
 }
需要注意:首先对括号内内容进行运算;“-” 号和除号要从表达式尾部开始提取,否则计算有误;“-” 号有负号和减号之分,解决办法是,在 “-” 号前有乘号和除号时,要按乘号或除号拆分;Math.formatFloat() 方法的运用。
使用效果图如下,存在bug或者文中有错误的话希望指出 [抱拳]
  
JS实现轻量级计算器的更多相关文章
- 使用html+css+js实现简易计算器
		
使用html+css+js实现简易计算器, 效果图如下: html代码如下: <!DOCTYPE html> <html lang="en"> <he ...
 - html+css+js实现科学计算器
		
代码地址如下:http://www.demodashi.com/demo/13751.html 项目描述 纯html+css+js实现一个科学计算器,支持平方开方指数对数等基本函数,支持键盘输入,有简 ...
 - js加减乘除在线计算器代码
		
js加减乘除在线计算器代码 在线演示本地下载
 - 项目:JS实现简易计算器案例
		
组件化网页开发下的: 步骤一:让页面动起来的JavaScript深入讲解 的 项目:JS实现简易计算器案例
 - js实现简单计算器
		
效果图: 刚开始做时没考虑到清零和退格两个功能,嘻嘻,后来加的整体与传统计算器比有点小瑕疵. 代码: <!DOCTYPE html><html><head> < ...
 - html、css、js实现简易计算器
		
学习HTML,CSS,JS一个月后,想着能自己是否能写出一个简单的东西,故编写了简易的计算器,之前也写过一个坦克大战,坦克大战的有些基本功能没有实现, 故也没有记录下来,想来,对这行初来咋到的,还是需 ...
 - 用js制作简易计算器及猜随机数字游戏
		
<!doctype html><html><head> <meta charset="utf-8"> <title>JS ...
 - 用js制作一个计算器
		
使用js制作计算器 <!doctype html> <html lang="en"> <head> <meta charset=" ...
 - 原生JS实现简易计算器
		
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
 
随机推荐
- Mac环境下.Net开发
			
Mono是一个由Novell公司(由Xamarin发起),并由Miguel de lcaza领导的,一个致力于开创.NET在Linux上使用的开源工程.它包含了一个C#语言的编译器,一个CLR的运行时 ...
 - 记忆 : Odata $count
			
在v4.0 的规范中,没有$inlineCount,只有$count. 但是在Entity 不支持$count,给出的原因是这样的, asp.net 的 web api 是支持Odata 的, 但是e ...
 - RHL 6.0学习日记, 先记下来,以后整理。
			
今天又遇到哪些问题呢? 1.配置网络的问题,我把网络配置文件胡乱改了,然后就上不了网了 因为一直都没怎么用到网络,网线都不怎么连接的,今天只是突然想ping一下,于是就Ping 了一下,一开始ping ...
 - 文件上传----FTP部署
 - mfc---CFileFind
			
使用CFileFind实现在指定路径下,查找指定类型文件 CFileFind.FindFile(FilePath + "\\*.*"),成功返回true,否则返回false CFi ...
 - (Mac OS平台)升级.NetCore1.0正式版小记
			
昨天终于发布了.NetCore1.0正式版.昨晚回去就顺手把手里的一个.NetCore项目升级了一下.还是遇到了一些问题,这里记录下吧. 1.Restore问题 这个问题一直都有,一直放那没去解决.主 ...
 - linux下实现自动部署tomcat的脚本
			
linux下实现自动部署tomcat的脚本 由于经常部署war到tomccat上,经常有一些重复的工作要做:停服务.备份war包.上传新的war包.启动服务.索性就写了一个自动部署的脚本. 脚本如下a ...
 - Maximum Depth of Binary Tree leetcode
			
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...
 - swift -- 单例
			
方式一: (类似OC) class SingletonDispatch{ class var shareInstance : SingletonDispatch { //结构体 struct Stat ...
 - 队列工厂之RedisMQ
			
本次和大家分享的是RedisMQ队列的用法,前两篇文章队列工厂之(MSMQ)和队列工厂之RabbitMQ分别简单介绍对应队列环境的搭建和常用方法的使用,加上本篇分享的RedisMQ那么就完成了咋们队列 ...