山寨版计算器 part II

今天来解决基础计算问题。

通过这几天对计算器的把玩(确实是“把玩”,朋友看我捧个计算器按下1+2=3然后托腮冥想的表情时都投来了崇拜的目光…问我你是在怀疑人生么…),尝试了几种描述工作方式的模型,以下一种是我认为最直观的:

首先是发动机盖下面的东西:)

开机后输入1+2=时,计算器都干了什么呢?

  1. 开机;
  2. 把1写入操作数1;
  3. 把+写入计算符号;
  4. 把2写入操作数2;
  5. 运行计算操作;
  6. 把计算结果3保存到结果中,并返回到显示屏。

实际应用时要考虑的东西就更多了,因为它不能只支持一次计算呀。比如:

显示屏上或者其他组件里随时都有可能存着其他东西,在任意时刻按下按钮时计算器应做出什么反应?比如:按下一个数字时,是要接着显示屏中现有的数字往下输,还是新开始一个数字?按下一个运算符时,是准备进行一次全新的计算呢,还是刚才输错了准备修改呢,还是要进行连续计算呢?

计算器是支持连续计算的,如果你输入了1+2,不停地按下=,你会得到3,5,7,9……是怎么实现的?

按下1+后直接按=可以得到2,计算器是怎么自行脑补“操作数2”的数值为1的呢?

一个数字里不能在开头出现多个0,如果有一个小数点后就不能再有第二个小数点,如何保证?

……

扫描二维码关注公众号,回复: 1806266 查看本文章

就问你晕不晕。

真正足够通用的、可以称得上工业化的计算器算法应该是基于状态机的,涉及到一定的编译原理知识,作为编程小白的我表示怕怕。通过我自己的总结,写了一套比较浅显的,能基本运行的算法,也算“原曲不使用”了吧:

【初始化条件】

       “显示屏”显示“0”,flag“倒下”,“操作数1”、“运算符”、“操作数2”、“结果”均为空。

【按下数字键[0-9.]时的算法】

  1. 如果“结果”存在,则清除所有组件的内容;
  2. 如果flag立起,则清除“显示屏”的内容,显示“0”,放倒flag;
  3. 如果“显示屏”显示“0”且按下的数字键是[0-9],则清除“显示器”的内容;
  4. 如果“显示屏”中的内容包含“.”且按下的数字键是“.”,则清除按下键的内容;
  5. 将当前按下键的内容添加到“显示器”内容的末尾;
  6. 若“运算符”为空,则将“操作数1”赋值为当前“显示器”内容,否则将“操作数2”赋值为当前“显示器”内容。

下面分别分析一下:

  1. 如果“结果”存在,则证明刚完成一次计算,(这一因果关系如何保证?就是由1本身保证的,因为只要发现“结果”存在,它立刻就被清除了。)此时需要进行新的计算了,刚才的所有数据都没有保存的必要了;
  2. 为什么要有这个flag?(这里立flag可不是为了打脸的:)它是[+-*/]的助手。设想一下如果没有这个flag,输入1+后“显示器”显示的仍是1,此时如果你想输2会接着现有的1而得到12,这不是你想要的。因此必须有个标志物,在刚刚按下“运算符”时点亮,其它时刻熄灭;
  3. 为了清除错误的输入,数字左端不能有多个0;
  4. 数字中不能有多个小数点;
  5. 核心步骤;
  6. 在离开函数前,要把新的数字写入操作数中,是“操作数1”还是“操作数2”?根据当前有没有“运算符”来确定。

【按下运算符[+-*/]时的算法】

  1. 如果“操作数1”为空,那么给它补一个“0”;
  2. 如果“操作数1”、“运算符”、“操作数2”均不为空,“结果”为空,则先进行一次计算,然后将结果写入“操作数1”,清空“操作数2”;
  3. 如果“操作数1”、“运算符”、“操作数2”、“结果”均不为空,则将结果写入“操作数1”,“操作数2”清空;
  4. 将当前按下的符号按键写入“操作符”;
  5. 清空“结果”;
  6. 立flag。

这里的2、3看上去很乱,它们是为了适应按下操作符前各个组件的状态。为什么要有步骤5呢?是为了确保下一次步骤2可以顺利进行。最后看到了吧,立flag。

 【按下=时的算法】

  1. 如果“结果”不为空,则将结果写入“操作数1”;
  2. 如果“操作数1”为空,那么给它补一个“0”;
  3. 如果“运算符”不为空且“操作数2”为空,则将“显示屏”上的数字写入“操作数2”;
  4. 根据当前的“运算符”进行计算,将计算结果保存在“结果中”并显示在“显示屏”上。

 3解决了上文中让你晕的那一段中“脑补操作数2”的问题。

+/-只要注意好当前操作的对象就可以了,是哪个操作数,还是结果。就不展开说了。

再提一下%,它比较特殊,有两种计算模式:

  1. 如果当前只有“操作数1”,则求“操作数1”/100的值,比如按下“5%”结果是“0.05”;
  2. 如果当前有“操作数1”、“运算符”、“操作数2”,则按下%时,“操作数2”将修改为“操作数1”的百分之“操作数2”,比如按下“5+10%=”,实际完成的计算是“5+5*10%”,操作数二变为0.5,最终的结果是5.5。

就快成功了,基础界面中的功能都已经实现完毕了。可是可是。。。

WTF????

to be continued

猜你喜欢

转载自www.cnblogs.com/roy-t/p/calc02.html