20200924-5 四则运算试题生成,结对

此作业的要求参见:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11245

结对伙伴:宫立秋

github中代码地址:https://github.com/amancer34/calculate.git

一、功能1 四则运算

支持出题4个数的四则运算题目,所有题目要求作者有能力正确回答 (提示:1/3 != 0.33333333333333333333333333333333,而是无限长)。

重点:要随机生成一个四则运算表达式,由作者从控制台输入答案,并判断答案是否与系统给出答案一致。

难点:判断作者输入的答案与系统给出的答案是否相等时,还要考虑结果是负数的情况,我们一开始没有考虑到,导致输入的负号程序接收不到,程序运行结果不对。

编程收获:

1、random.randint(a,b)函数中随机数是可以取到b的。

2、eval()函数可以用来执行一个字符串表达式,并返回表达式的值。

运行截图:

 补充截图:

主要代码:

#产生四则运算表达式
def ques():
    operators = ['+','-','*','/']
    #随机产生运算符
    i1 = random.randint(0,3)
    i2 = random.randint(0,3)
    i3 = random.randint(0,3)
    #随机产生四个数
    number1 = random.randint(1,10)
    number2 = random.randint(1,10)
    number3 = random.randint(1,10)
    number4 = random.randint(1,10)
    ques = str(number1) + operators[i1] + str(number2) + operators[i2] + str(number3) + operators[i3] + str(number4)
    print(ques)
    return ques
    
#判断输入的数据是否正确
def result():
    total = 0
    for i in range(20):
        question = ques()
        res = eval(question)
        ans = input("? ")
        if str(res) == str(ans):
            print("答对啦,你真是个天才!")
            total += 1
        else:
            print("再想想吧,答案似乎是%f" %res)
    print("一共答对" + str(total) + "道题," + "共20道题!")
            
if __name__ == "__main__":
    #创建对象
    parser = argparse.ArgumentParser()
    #添加参数-c
    parser.add_argument("-c","--cin")
    #解析添加的参数
    args = parser.parse_args()
if args.cin == None: result()

功能2 支持括号

重点: 随机生成括号,并添加在功能1中生成的四则运算表达式的所有可能位置。

难点:考虑到括号可能在表达式中出现的所有位置,以及左括号出现后与之所匹配的右括号可能出现的位置。

编程收获:

随机生成括号时也要加if判断确保左括号与右括号是相匹配的,如果只靠random函数随机生成,可能导致左右括号不匹配,使得运算结果不正确。

运行截图:

补充截图:

主要代码: 

#产生四则运算表达式
def ques():
    brackets = ['(','',')']
    operators = ['+','-','*','/']
    #随机产生运算符
    i1 = random.randint(0,2)
    i2 = random.randint(0,3)
    i3 = random.randint(0,3)
    #随机产生四个数
    number1 = random.uniform(0,1)
    number1 = Fraction(number1).limit_denominator(10)
    number2 = random.uniform(0,1)
    number2 = Fraction(number2).limit_denominator(10)
    number3 = random.randint(1,10)
    number4 = random.randint(1,10)
    #随机产生左括号
    left1 = random.randint(0,1)
    left2 = random.randint(0,1)
    left3 = random.randint(0,1)
    #随机产生右括号
    right1 = random.randint(1,2)
    right2 = random.randint(1,2)
    right3 = random.randint(1,2)
    #括号匹配
    if left1 == 0:
        left2 = 1
        left3 = 1
        if right1 == 2:
            right2 = 1
            right3 = 1
        else:
            right2 = 2
            right3 = 1
    else:
        if left2 == 0:
            left3 = 1
            right1 = 1
            if right2 == 2:
                right3 = 1
            else:
                right3 = 2
        else:
            left3 = 0
            right1 = 1
            right2 = 1
            right3 = 2
    ques = brackets[left1] + str(number1) + operators[i1] + brackets[left2] + str(number2)
    ques += brackets[right1] + operators[i2] + brackets[left3] + str(number3) + brackets[right2]
    ques += operators[i3] + str(number4) + brackets[right3]
    ques = str(ques)
    return ques

功能3 限定题目数量,"精美"打印输出,避免重复

重点:由作者输入题目数量,程序生成相应数量的四则运算表达式,并将运算结果与题目对齐输出在屏幕及文件右边。

难点:在控制台输入题目数量时要用到argparse模块,通过其中的add_argument()函数将“-c”这个参数添加到命令行,否则会报错。

编程收获:

1、将表达式加等号后要将其赋给一个新的变量,加上等号后的字符串用eval()函数不能返回正确结果。

2、可以用isdigit()函数判断输入的是否为整数

3、用format()函数可以格式化输出,将运算结果输出在右端。

运行截图:

主要代码:

#命令行输入题目数目
def command_input(num):
    data = open('data.txt','w+')
    if num.isdigit():
        for i in range(int(num)):
            question = ques()
            question1 = question + '='
            res = Fraction(eval(question)).limit_denominator(100000)
            print('{:<50}{:<25}'.format(question1,str(res)))
            print('{:<50}{:<25}'.format(question1,str(res)),file = data)
    else:
        print("题目数量必须是正整数。")

if __name__ == "__main__": #创建对象 parser = argparse.ArgumentParser() #添加参数-c parser.add_argument("-c","--cin") #解析添加的参数 args = parser.parse_args() if args.cin == None: result() else: command_input(args.cin)

功能4 支持分数出题和运算

重点:将运算结果表示为一个分数,并约分。

难点:在得到运算结果后要分成分子、分母两个部分进行保存,同时对其进行输出时,要转换成十进制形式输出,如果直接输出会得到错误的结果。

编程收获:

1、将一个假分数转化为一个带分数的形式时使用“//”可以直接得到整数部分。

2、random.uniform(a,b)随机生成的实数范围是[a,b],random.random()函数的下限才无法取到。

3、Fraction()函数可以将随机生成的小数转化为分数,并对其进行自动约分。

4、limit_denominator(max_denominator)用于返回一个分母不大于max_denominator且最接近原值的分数,避免浮点数和有理数转化失真。

运行截图:

补充截图:

主要代码:

#将分子分母转换为十进制数
def take_decimalism(dicts = {}):
    j= len(dicts)-1
    sum1 = 0
    for i in range(0,len(dicts)):
        if j < 0:
            break
        sum1 = int(dicts[j]) * int(math.pow(10,i)) + sum1
        j = j-1
    return sum1        
    
#遍历结果,将分子、分母存储到两个字典中并约分
def traversal_dist(res):
    d1={}
    d2={}
    count1=0
    count2=0
    flag=0
    sign=0
    for i in res:
        if i=='-':
            sign=i
            continue
        if i=='/':
            flag=1
            continue
        if flag==0:
            d1[count1]=i
            count1=count1+1
        else:
            d2[count2]=i
            count2=count2+1
    #分子
    numerator = take_decimalism(d1)
    #分母
    denominator = take_decimalism(d2)
    if denominator == 0:
        return numerator
    else:
        w1=numerator // denominator
        w2=numerator % denominator
        answer=0
        if sign=='-':
            if w1==0:
                answer=sign+str(w2)+"/"+str(denominator)
            else:
                answer=sign+str(w1)+" " +str(numerator)+"/"+str(denominator)
        else:
            if w1==0:
                answer=str(w2)+"/"+str(denominator)
            else:
                answer=str(w1)+" " +str(numerator)+"/"+str(denominator)
        return answer

二、结对编程体会:

1、能更快的解决问题。一个人编程时,如果遇到某些问题,需要反复琢磨,但是结对编程可以互相交流对问题的想法,能更快找到一个解决办法。

2、能更快的通过测试。测试时可能会有一些错误,自己挑错可能会有些费力,让对方给自己挑错,能更快找到出错的地方并修改,从而更快的通过测试。

3、有时编程会感到枯燥,但结对编程会相对减少枯燥感。

当然在编程时有时会因想法不同而产生一些争议,但我认为能更好的提高效率,优点是大于缺点的。

三、至少5项在编码、争论、复审等活动中花费时间较长,收获较大的事件:

1、在功能1中我们因为将用eval()函数返回的结果转化为了int及float导致对于负数的负号接收不到,运行结果不对。

2、在功能2中只随机生成了括号没用if判断做括号的匹配,导致括号不对,生成的表达式也不对,一直出错。

3、在功能3中因在生成的表达式中又添加了“=”,用eval()函数无法得到结果,需要将新的字符串重新赋给一个变量,再将原有的式子用eval()函数得到结果。

4、在功能4中需要将运算结果中的分子、分母分别遍历存储最后再转化为十进制输出。

5、在功能4中分子、分母转化为十进制时从列表或字典中取得第一个数是个位的数,也是最小的数,转化为十进制要乘10的0次方,我们在做的时候将顺序弄反,导致结果不对;输出时还要考虑到有负号和没负号两种情况。

四、结对编程截图:

posted @ 2020-10-07 13:51  amancer  阅读(125)  评论(0编辑  收藏  举报