说来惭愧,大一这一年这么也就过去了,到头来感觉也没学到什么太多,虽然学了点简单的算法但也没练习太多【回想起被一个哈夫曼树卡一天多的黑历史 = =b】
然后当年自己说的要学前端结果到头来也没怎么学,在放假前也就是会写个课程表出来的程度,买的HTML5+CSS3的书也积了灰了。出于各种原因吧,ACM我也退出了,大概是找到了自己真正想学什么想做什么吧。于是这个假期、未来的假期、平时我都有了足够的时间去学我想学的东西,去做我想做的事情。比如趁着现在,学学前端,搞搞开发,写写游戏策划……
闲话也就说这么多吧,下面是正题:
经过了不到一周的自学,加上学校小学期让学有余力的同学试着用MFC做个简单计算器出来,我就想,反正本质就是让我们这些秒杀正常教学安排的人找点事干的东西,不如自学一波HTML5吧,然后发现稍微想上点功能没有JS就寸步难行,于是开始同时学习JS,也借着“写计算器”这一契机,让自己挑战用HTML5+JS写个计算器出来。
HTML5部分主要是负责了排版,真正的功能都由JS完成。说来也蛋疼,JS没有栈……那只好自己写一个function模拟了……随后就是基本的中缀转后缀、计算后缀表达式的部分,于是又看了一遍各个大神的博客的内容,才发现一个尴尬的问题:以前老是上课讲这部分的时候,有的地方讲错了!怪不得我那时候代码总有BUG……= =b 这个坑的位置在于如果栈顶是左括号则该运算符直接入栈。
整体做下来给我的感觉就是,核心功能并不复杂,也就那点事而已。难就难在一些小功能的实现和错误处理,比如处理负数,处理可以省略乘号输入的时候,角度与弧度转化……等等。有些地方蛋疼就蛋疼在会牵连一些别的地方出BUG,而且这玩意不会报错……这一遭下来也算是让自己的心态好了很多吧。写这种东西还是挺锻炼人的。
如果要说最蛋疼的部分,那应该是对于各种错误判定和处理以及可能的“骚操作”处理,可能对于大多数人比较好想的是除0、tan90°、反三角函数的定义域,以及胡乱输运算符这些问题。但是实际做起来就会发现,“骚操作”还真有不少,比如多个小数点?e.x、x.e、.8×.2这种?(然而还好JS貌似对第三种有处理),.cos(x)?负数阶乘小数阶乘?(小数阶乘真的跪了,暂时用斯特林公式顶一下吧OTZ)以及浮点误差。【大概目前能回想起来的有这些,但肯定不全】这几天我手机上自带的计算器都快被我玩坏了233
最终,手机上科学计算器的功能也都基本实现了,最后我发现这玩意打包成app还挺简单,于是顺便做了点图打包了个apk,手机上也能玩,就是排版残念……下一步准备学习排版。【又是不知不觉写了七百多行……想起我那个用Ruby写的简易QTE了OTZ】
最后附上Beta版的全部代码:
<!DOCTYPE html>
<html>
<!--
作者:Caronell Arnold
时间:2018-07-11
描述:小辣鸡计算器,JS + HTML5 练习
-->
<head>
<meta charset="utf-8"/>
<title>小辣鸡计算器</title>
<script language="JavaScript">
var Angel_Mode = "deg"; //弧度制和角度制
var snd = 0; // 第二模式
//#===============================================
//# ● 栈的模拟
//#===============================================
function Stack()
{
this.dataStore = [];
this.count = 0;
this.push = push;
this.pop = pop;
this.size = size;
this.clear = clear;
this.top = top;
this.empty = empty;
function push(x)
{
this.dataStore[this.count++] = x;
}
function pop()
{
this.count -= 1;
}
function size()
{
return this.count;
}
function clear()
{
this.count = 0;
}
function top()
{
if(this.count == 0)
throw err = new Error("pop警告:当前栈为空。");
else
return this.dataStore[this.count-1];
}
function empty()
{
if(this.count == 0)
return true;
else
return false;
}
}
//#===============================================
//# ● 判断是否为运算符
//#===============================================
function is_operator(x)
{
if((x>='0' && x<='9') || x=='π' || x=='e' || x==' ' || x=='.')
return false;
else
return true;
}
//#===============================================
//# ● 计算阶乘
//#===============================================
function factorial(n)
{
var t=n.toString().indexOf(".");
if(n == 0)
return 1;
else if(t > 0)
return Math.sqrt(2*n*Math.PI)*Math.pow(n/Math.E,n);
else
return n*(factorial(n-1));
}
//#===============================================
//# ● 格式化运算式
//#===============================================
function format(str)
{
var i;
var tmp="";
for(i=0;i<str.length;++i)
{
if(is_operator(str[i]))
{
if(str[i] == 'a') // 反三角函数
{
if(i>0 && !is_operator(str[i-1]) && str[i-1]!=' ')
tmp = tmp + " × ";
tmp = tmp + str[i]+str[i+1]+str[i+2]+str[i+3] + " ";
i += 3;
}
else if(str[i]=='s' || str[i]=='c' || str[i]=='t')
{
//三角函数
if(i>0 && !is_operator(str[i-1]) && str[i-1]!=' ')
tmp = tmp + " × ";
tmp = tmp + str[i]+str[i+1]+str[i+2] + " ";
i += 2;
}
else if(str[i] == 'l')
{
//对数
if(i>0 && !is_operator(str[i-1]) && str[i-1]!=' ')
tmp = tmp + " × ";
tmp = tmp + str[i]+str[i+1] + " ";
i += 1;
}
else if(str[i] == '√')
{
if(i>0 && !is_operator(str[i-1]) &&a