计算化学公社

标题: 请问大拿这道题该怎么写? [打印本页]

作者
Author:
zyj19831206    时间: 2019-9-18 19:03
标题: 请问大拿这道题该怎么写?
怎么用C++实现下面这道题?
写一个计算器,支持三个运算数。
比如用户输入 2 * 3 + 2,应输出:8
注意要保证乘除先运算。没有括号。




作者
Author:
granvia    时间: 2019-9-18 20:50
首先parse输入字符串为5个fields,第1,3,5个转为数字a,b,c,第2,4个是运算符x,y。因为一共只有两个运算,所以很容易比较出先算axb还是先算byc
作者
Author:
DoubeeTwT    时间: 2019-9-19 10:42
(1) 先将a保存在一个数组中,然后读入符号
(2) 判断符号是加减还是乘除
      如果是乘除:直接运算数组最后一位与新加入数字的乘积然后替换数组最后一位
      如果是加减:将新加入的数字添加到数组最后
(3) 全部读取完毕后累加整个数组

以你的题目为例,数组如下一步步变化:
[2]
[6]
[6,2]

以1+2*3+4*5为例:
[1]
[1,2]
[1,6]
[1,6,4]
[1,6,20]
作者
Author:
k64_cc    时间: 2019-9-19 11:13
就加减和乘除两个优先级的话你压个栈就好了啊。加减就压栈,乘除就弹出上一个,算数,再压进去。然后最后再把栈内元素累加。
哦你就算仨数,那算了。

作者
Author:
卡开发发    时间: 2019-9-20 10:07
存3个数字和2个足矣,能计算任意长度的计算。这里用python写了个草稿在上面加了注释。C++版本和Fortran90版本放在附件里面,尽管编程语言不同编程的思想没啥差别。当然python确实有更简单的做法,当然最简单的大概就是exec或ast.literal_eval了,那也就没啥好讨论的了。
  1. #作者:卡开发发
  2. #日期:2019-9-20
  3. #计算加减乘除


  4. #给定a、b两个数和当中的计算符号,返回计算结果。
  5. def calc(a,string,b):
  6.         if string=='+':
  7.                 return a+b
  8.         if string=='-':
  9.                 return a-b
  10.         if string=='*':
  11.                 return a*b
  12.         if string=='/':
  13.                 return a/b

  14. #键盘输入获取计算的表达式。
  15. string=input('input the expression:')
  16. #保存三个数和两个符号,
  17. #例如a+b*c会被保存为tmp=[a,b,c],sign=['+','*']。
  18. tmp=[0,0,0]
  19. sign=['+','+']

  20. #遍历所输入的字符串
  21. for i in range(len(string)):
  22.         s=string[i]
  23.         #遇到数字就x10+新的数字,这样就将连续的数字构成的字符数组转化为数字,
  24.         #即'abc..'=str(10*(10*a+b)+c...)
  25.         #通过ASCII来判断是否为数字。
  26.         if ord(s)>=48 and ord(s)<=57:
  27.                 tmp[2]=float(tmp[2]*10+ord(s)-48)
  28.         #遇到符号就对前面三个数和两个符号进行计算。
  29.         if s=='*' or s=='/'or s=='+' or s=='-':
  30.                 #如果第二个符号是乘除号,直接计算这乘法,
  31.                 #这样就相当于将tmp[1]和tmp[2]还有sign[1]合并为一个新的tmp[2]。
  32.                 #例如a+b*c+d...,表示为tmp=[a,b,c],sign=['+','*'],
  33.                 #现在遇到字符是第三个符号'+',则计算b*c,
  34.                 #计算后的结果就变成了tmp=[a,a,b*c],sign=['+','+']。
  35.                 if sign[1]=='*' or sign[1]=='/':
  36.                         tmp[2]=calc(tmp[1],sign[1],tmp[2])
  37.                         tmp[1]=tmp[0]
  38.                         sign[1]=sign[0]
  39.                 else:
  40.                         #如果两个符号都是加减号,直接计算第一个加减法,
  41.                         #这样就相当于将tmp[0]和tmp[1]还有sign[0]合并为一个新的tmp[1]。
  42.                         #例如a+b+c*d...,表示为tmpp=[a,b,c],sign=['+','+'],
  43.                         #现在遇到字符是第三个符号'*',则计算a+b,
  44.                         #计算后结果变成tmp=[a,a+b,c],sign=['+','+']。
  45.                         if (sign[1]=='+' or sign[1]=='-') and \
  46.                         (sign[0]=='+' or sign[0]=='-'):
  47.                                 tmp[1]=calc(tmp[0],sign[0],tmp[1])
  48.                 #扔掉tmp[0]和sign[0],
  49.                 #tmp[2]设置为0用来存放新的数字,
  50.                 #sign[1]用来存放当前读取到的符号。
  51.                 tmp[0]=tmp[1]
  52.                 tmp[1]=tmp[2]
  53.                 tmp[2]=0
  54.                 sign[0]=sign[1]
  55.                 sign[1]=s

  56. #读取到字符串末尾后,表达式就会变成三个数的运算。
  57. #如果加号在前面,如a+b*c,先计算b*c,其余情况按照顺序计算。
  58. if sign[0]=='+' or sign[0]=='-':
  59.         result=calc(tmp[0],sign[0],calc(tmp[1],sign[1],tmp[2]))
  60. else:
  61.         result=calc(calc(tmp[0],sign[0],tmp[1]),sign[1],tmp[2])
  62. #输出计算结果。
  63. print(string+'='+str(result))
复制代码
(, 下载次数 Times of downloads: 1)

(, 下载次数 Times of downloads: 2)

作者
Author:
granvia    时间: 2019-9-20 12:19
卡开发发 发表于 2019-9-20 10:07
存3个数字和2个足矣,能计算任意长度的计算。这里用python写了个草稿在上面加了注释。C++版本和Fortran90版 ...

还得考虑输入数字可能是浮点数和负数吧?
作者
Author:
卡开发发    时间: 2019-9-20 12:51
本帖最后由 卡开发发 于 2019-9-20 13:19 编辑
granvia 发表于 2019-9-20 12:19
还得考虑输入数字可能是浮点数和负数吧?

负数不影响,浮点数的话就把读取数字部分做一下处理就行了,没有多复杂。22行下面:
  1. sign=['+','+']
  2. frac=False
  3. frac_len=0
复制代码
30行下面:
  1.     if ord(s)>=48 and ord(s)<=57 or s=='.':
  2.         if s=='.':
  3.             frac=True
  4.             s='0'
  5.         if not frac:
  6.             tmp[2]=float(tmp[2]*10+ord(s)-48)
  7.         else:
  8.             tmp[2]=float(tmp[2]+(ord(s)-48)/10**frac_len)
  9.             frac_len+=1
复制代码
57行下面:
  1.         tmp[2]=0
  2.         frac=False
  3.         frac_len=0
复制代码

其他语言的代码修改思路是一样的,就不再写一遍了。







欢迎光临 计算化学公社 (http://bbs.keinsci.com/) Powered by Discuz! X3.3