zoukankan      html  css  js  c++  java
  • 第四次作业-四则运算

    前言

      •  作业要求地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997

      •  结对伙伴:宋雨http://www.cnblogs.com/songyuu/

      •  git:https://git.coding.net/Vrocker/f4.git

     


     

    要求一

      •  具体要求:参考《构建之法》第4章两人合作,结对编程上述功能,要求每人发布随笔1篇 (代码是共同完成的,博客是分别完成的)。 (1) 给出每个功能的重点、难点、编程收获。(2)给出结对编程的体会,以及 (3) 至少5项在编码、争论、复审等活动中花费时间较长,给你较大收获的事件。

    一、每个功能的重点、难点

    1.功能一

      实现这个功能的重点是在于随机生成参与运算的数字和四个运算符。在Python中,random模块可以用于生成随机数。这样很方便的使用了这一模块下的部分函数,来实现这一功能。

      部分代码如下:

        def _f4(self):
            from random import randint as r
            from random import uniform as ru
            from fractions import Fraction as f
            ops = ['+', '-', '*', '/']
            bra = ['(', '', ')']
            _l1 = r(0, 1)
            _l2 = r(0, 1)
            _l3 = r(0, 1)
            _r1 = r(1, 2)
            _r2 = r(1, 2)
            _r3 = r(1, 2)
    

      

    2.功能二

      这个功能中加入了括号的运算。括号参与运算是最大的难点。

      本科期间学习的数据结构这门课程中,在讲到栈与队列的时候,逆波兰即后缀表达式是栈在表达式求知中的应用。这个应用是栈比较常见的,而且十分常用。所以看到这个要求加上题目中老师的提醒,我就开始翻找数据结构书来寻找相应的方法。同时用栈可以很好的解决括号匹配,这样一来两者结合可以通过栈来完成需求。经过查阅数据结构书加上自己的思考尝试解决这一难题。

      括号匹配算法总结如下:

      1、初始化一个空栈,开始顺序读入括号。

      2、如果是右括号,则或者是置于栈顶的最急迫期待得以消解,或者是不合法的情况(括号序列不匹配,退出程序)。

      3、若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性降了一级。算法结束,栈为空,否则括号序列不匹配。

      根据这一算法,可以解决括号匹配的问题。

      同时表达式求值的实现是栈应用的一个典型的例子。中缀表达式不仅依赖运算符的优先级,同时还要处理括号。后缀表达式的运算符在操作数后面。在后缀表达式中已考虑了运算符的优先级,没有括号,只有操作数和运算符。并且中缀表达式和后缀表达式可以相互转换。通过后缀表达式计算相应式子的值,其过程为:

      1、顺序扫描表达式的每一项

      2、如果是操作数,则将其压入栈中

      3、如果是操作符<op>,则连续从栈中推出两个操作数,x和y,形成运算的指令x<op>y

      4、将计算的结果重新压入栈中。

      5、当表达式所有的项豆扫描并且处理完毕后,栈顶存放的就是最后的计算结果。

      根据书中的介绍,栈可以很好的解决这一需求。在最开始分配任务的时候,我一开始想用c++来编写程序,因为自己相对于其他语言比较熟悉c++,所以在考虑这一个问题的时候我当时也是想要采用c++来实现。自己根据书中的范例代码并且查阅了网上相关代码,尝试进行改写,来满足题目需求。

      首先读取随机生成的表达式,然后用上次作业用到的vector,构造vector<string>储存成普通的中缀表达式然后遍历vector<string>再用刚刚提到的算法利用栈来构造后缀表达式。最后遍历构造好的vector<string>中存放在后缀表达式对弹出栈的两个操作数进行运算,将结果压入栈中。则最后剩余在栈中的一项就是计算的最终结果。c++的部分代码如下:

     1     for (auto &oper : vec) {  
     2         if (oper == "+" || oper == "-") {                
     3             while (true) {  
     4                 if (sta.empty() || sta.top() == "(")  
     5                     break;  
     6                 p_vec.push_back(sta.top());  
     7                 sta.pop();  
     8             }  
     9             sta.push(oper);  
    10         }  
    11         else if (oper == "*" || oper == "/") {               
    12             while (true) {  
    13                 if (sta.empty() || sta.top() == "+" ||  
    14                     sta.top() == "-" || sta.top() == "(")  
    15                     break;  
    16                 p_vec.push_back(sta.top());  
    17                 sta.pop();  
    18             }  
    19             sta.push(oper);  
    20         }  
    21         else if (oper == ")") {                                 
    22             while (true) {  
    23                 if (sta.top() == "(") {  
    24                     sta.pop();  
    25                     break;  
    26                 }  
    27                 p_vec.push_back(sta.top());  
    28                 sta.pop();  
    29             }  
    30         }  
    31         else sta.push(oper);  
    32     }  
    33     while (!sta.empty()) {  
    34         p_vec.push_back(sta.top());  
    35         sta.pop();  
    36     }  
    c++

      

      不仅仅是计算,括号的生成顺序也是这个要求的难点。也可以定义栈用逆波兰的方法来解决。

      因为我和我的结对伙伴都想用python来完成这次作业,所以如果要用栈那么c++的代码就要改写成python的。一开始在看题目要求的时候,观察到操作数是固定的四个数字,就采用直接固定四个操作数,没有采用栈而是直接判断括号的优先级,来生成括号并且计算。在之后的python编写中因为我自己对python学习还是太少,编写不出python的逆波兰方法。在尝试多次后,甚至想把作业重新用c++编写,但是换编程语言的工作量太大,所以就用比较原始的方法完成这个需求。

      在此之后还会不断尝试用python实现逆波兰。

    3.功能三

      这个功能的主要难点是在于命令行参数的实现。

      在上次作业中,c++语言的命令行参数花费了我很多时间才会完全使用。python中可以用argparse标准库解决。它是解析命令行参数和选项的标准模块。在学习argparse模块的使用方法后,实现了python 的命令行参数功能。总体感觉比c++要简便不少。

      部分代码如下:

    1     import argparse
    2     parser = argparse.ArgumentParser()
    3     parser.add_argument("-c", "--cin")
    4     args = parser.parse_args()
    5     if args.cin == None:
    6         f4()._f4_input()
    7     else:
    8         f4()._f4_integer_parser(args.cin)

    4.功能四

      这个功能中,最重要的就是支持分数。这个功能宋雨同学花费了很长时间解决了这个难点很多的功能。经过他的讲解介绍,用fractions标准库可以实现这一功能。采用python内置函数eval()。但eval()函数的输出为浮点数,故采用这一函数生成的分数分子分母位数都很多。测试之后发现不满足题目的要求,所以在宋雨同学的解决意见下限制输出的位数。经过实验,发现可以实现。所以采用了这一方法。

      部分代码如下:

    1     def _f4_answer(self,eq):
    2         from fractions import Fraction as f
    3         _answer = f(eval(eq)).limit_denominator(1000)
    4         _answer = str(_answer)
    5         return(_answer)

     

     

    二、体会

      在开始编写程序的时候,决定选择了python进行编写。因为我对python掌握很不好,所以本次主要的代码都是由宋雨同学完成,给我了很多帮助,我也在结对编程的过程中不断学习python。

      因为我自己的原因,相比较python,c++我掌握的相对好一些,所以在遇到难题的时候想把代码换成c++。但是因为工作量太大,而且我认识到不能回避难题,所以接着用python进行编写。这次结对编程我体会到相互合作的重要性,结对伙伴不仅能给自己帮助也能共同进步一起努力。

    三、花费时间较长,给你较大收获的事件

      1、一开始没有采用面向对象来编写代码,在讨论之后将代码改成oop方式。

      2、栈的问题花费的时间很多,对python 掌握还是太差。

      3、分数功能的实现,包括查资料测试都花费了很多时间。

      4、进行单元测试的时候框架换了很多。

      5、一起编写的时候,宋雨同学对我讲解了很多python的知识。让我对python的学习有了信心。


    要求二

      地点:寝室

      电脑:msi、win10

      软件:pycharm

      语言:python

    照片:


    测试截图

    1

    2

    3

     

  • 相关阅读:
    hdu 2014 青年歌手大奖赛_评委会打分
    java 图像灰度化与二值化
    hdu 2010
    如何搞定IE+google双内核的360浏览器表单自动回填兼容问题
    多预览小图焦点轮播插件lrtk
    多功能前台交互效果插件superSlide
    自适应标题延展线写法
    二级菜单延迟隐藏
    各种浏览器的Hack写法(chrome firefox ie等)
    jQuery treetable【表格多重折叠树功能及拖放表格子元素重新排列】
  • 原文地址:https://www.cnblogs.com/vrocker/p/7650258.html
Copyright © 2011-2022 走看看