Implement an instance of a calculator

PHP中文网
Release: 2017-06-20 14:35:47
Original
1366 people have browsed it

Assignment: Calculator development

 (1) Implementation of addition, subtraction, multiplication, division and extension priority analysis;

  (2) User input 1 - 2 * ( (60-30 +(-40/5) * (-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) and other similar formulas, you must parse the (), +, -, *, / symbols and formulas inside. After the operation To get a result, the result must be consistent with what a real calculator would produce.

The code is as follows:

 1 import re 2  3 formula = '1 - 2 * ( (60-30 +(-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 ) * (-40/5)) - (-4*3)/ (16-3*2) )' 4 #formula = "(1++1)" 5 def modify(formula_deep): 6     '''程序修饰函数,去除空格和括号''' 7     '''去除运算中出现的+- -- ++ -+ 等情形''' 8     formula_deep = re.sub("[() ]","",formula_deep)   #替换空格和空号 9     formula_deep = re.sub("\+-","-",formula_deep)    #替换+-为-10     formula_deep = re.sub("--",'+',formula_deep)     #替换--为+11     formula_deep = re.sub("-\+",'-',formula_deep)12     formula_deep = re.sub("\++","+",formula_deep)13     return formula_deep14 15 def multiply_divide(formula_deep):16     '''计算乘除'''17     '''由于乘除是首先计算的,我们的思路是,首先计算乘除,然后把计算的结果替换进去,就可以得到只剩加减的情形'''18     calc_sign = re.findall("[+-]",formula_deep)    #提取字符串中所有的加减号19     calc_list = re.split("[+-]",formula_deep)      #以加减号进行分割,得到乘除20     '''由于我们得到的calc_list:['', '9', '2*5/', '3', '7/3*99/4*2998', '10*568/14'],里面由于-号引起的麻烦,-9被分割了,2*5/等'''21     if calc_list[0] == '':22         '''处理列表开头“”空的情况,说明这里是负数,被我们分割掉了要重新进行合并'''23         calc_list[1] = calc_sign[0] + calc_list[1]24         del calc_sign[0]25         del calc_list[0]26     for num,line in enumerate(calc_list):27         '''处理2*5/的情形,说明这种后面除的是一个负数,因为只有负数才会出现这种情况2*5/-3被分割了,需要合并'''28         if line.endswith("/") or line.endswith("*"):29             '''如果结尾包括乘除号,说明是负数被拆分了'''30             calc_list[num+1] = calc_list[num] + calc_sign[num] + calc_list[num+1]31             del calc_sign[num]32             del calc_list[num]33     '''下面进行乘除的正式运算,上面都是进行格式转换'''34     for index,string in enumerate(calc_list):35         '''首先提取编号,便于后面替换运算出来的值'''36         if "/" in string or "*" in string:37             mul_div_sign = re.findall("[/*]",string)38             mul_div_list = re.split("[/*]",string)39             calc_value = None40             for e_index,e in enumerate(mul_div_list):41                 if calc_value:42                     if mul_div_sign[e_index-1] == "/":43                         calc_value /= float(e)44                     elif mul_div_sign[e_index-1] == "*":45                         calc_value *= float(e)46                 else:47                     calc_value = float(e)48                 calc_list[index] = calc_value49         else:50             pass51     '''计算值'''52     value = None53     for k,v in enumerate(calc_list):54         '''计算加减的情况'''55         if value:56             if calc_sign[k-1] == "-":57                 value -= float(v)58             elif calc_sign[k-1] == '+':59                 value += float(v)60         else:61             value = float(v)62     return value63 64 65 def main(formula):66     '''程序主入口,生成带括号的情况'''67     while True:68         formula_deep = re.search("\(.[^()]+\)",formula)69         if formula_deep:70             formula_deep = formula_deep.group()71             formula_list = modify(formula_deep)72             '''得到修整好要计算的字符串,现在开始进行计算-9-2*5/-3+7/3*99/4*2998+10*568/14'''73             calc_value = multiply_divide(formula_list)74             formula = formula.replace(formula_deep,str(calc_value))75         else:76             '''处理不带括号的情形'''77             formula = modify(formula)78             calc_last_value = multiply_divide(formula)79             print("formula:",calc_last_value)80             exit()81 82 if __name__=="__main__":83     main(formula)
Copy after login

Program running process:

General idea: We know that to calculate the format of the above string, you can use eval() function, but here we have to write a calculator ourselves; we know that the priority of mathematical operations is that the parentheses have the highest priority, and the things in the parentheses are operated first, so our idea is to match the parentheses in the memory and then perform Operation, after matching the contents in the memory brackets, we calculate, and then use the calculated value to replace the value at the original position in the string until there is no bracket position in the string. At this time, we follow the normal order of operations. to perform calculations.

1. For regular matching, first find the memory brackets; the code is as follows:

formula = '1 - 2 * ( (60 -30 +(-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 ) * (-40/5)) - (-4*3)/ (16-3 *2) )'
 formula_deep = re.search("\(.[^()]+\)",formula)
 print(formula_deep.group())

## The running results are as follows:

(-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 )

Above we observed the string extracted from the memory. We can see that there are many places that need to be modified. There are many spaces in the string, which will affect our calculation and the calculation process. We don't need the parentheses, so we'll get rid of them too.

2. Remove spaces and brackets;

formula_deep = re.sub("[() ]", "",formula_deep)

## Run as follows:

-9-2*5/-3+7/ 3*99/4*2998+10*568/14

3. After obtaining the above string, when we perform the operation layer by layer, +-, -+, ++, -- and other situations may occur. This It also needs to be processed. Since it is the first level now, the problem cannot be seen. After the operation, if the memory gets a negative number, then if there is + or - outside the previous brackets, it will become +-, -, etc., this Sometimes it doesn't work, we have to deal with it;

formula_deep = re.sub(

"\+-",'-',formula_deep) formula_deep = re.sub("-+",
'-',formula_deep)  formula_deep = re.sub("\++",
"+",formula_deep) formula_deep = re.sub("--",
'+',formula_deep)
Run as follows:

-9-2*5/-3+7/3*99/4*2998+10*568/14

4. When the above processing is completed, the calculation officially starts. We know that the calculation must first calculate multiplication and division, because multiplication and division have the highest priority, because multiplication and division must be found first, and addition and subtraction can be calculated after the calculation is completed;

calc_sign = re.findall(

"[+-]",formula_deep) calc_list = re.split("[+-]",formula_deep)
 print(calc_list)
 print(calc_sign)

Run as follows:

['', '9', '2*5/', '3', '7/3*99/4*2998 ', '10*568/14']
 ['-', '-', '-', '+', '+']

## We got the calculation list, and operation symbols, ['', '9', '2*5/', '3', '7/3*99/4*2998', '10*568/14'] There are also problems inside. First of all, the first element of the list is "" empty, which means that this situation occurs only when it is preceded by a - sign. Such situations need to be merged, and there are 2*5/ , this description is also followed by a negative number, which must be processed before the budget calculation can be performed. Why does this happen? This is because during the operation, we use "+" or "-" to split the string. This will cause if it is a negative number, it will be split. At the beginning, the front will be split by one Empty, this will cause errors in our calculations because we need to make modifications.

5. Modify the above operation:

if calc_list[0] == "" : ​ calc_list[
1] = calc_sign[0] + calc_list[1]
del calc_list[0]
del calc_sign[ 0]
 print("calc_list:",calc_list)
 print("calc_sign:",calc_sign)
 for index, e in enumerate(calc_list):
if e.endswith("/") or e.endswith("*"):
'''The description is followed by a negative number and needs to be corrected'''
calc_list[index+1] = calc_list[index] + calc_sign[index] + calc_list[index+1]    
del calc_list[index]
 del calc_sign[index]

 print("calc_list:",calc_list )
 print("calc_sign:",calc_sign)

Run as follows:

calc_list: ['- 9', '2*5/', '3', '7/3*99/4*2998', '10*568/14']

 calc_sign: ['-', '-', '+ ', '+'] calc_list: ['-9', '2*5/-3', '7/3*99/4*2998', '10*568/14']
calc_sign : ['-', '+', '+']

As can be seen from the above, we made the correction in two strokes. The first time we removed the "" space at the beginning Element problem; the second time the case of multiplication and division followed by negative numbers is raised;

    6、这个时候,我们就要进行计算了,我们首先遍历calc_list: ['-9', '2*5/-3', '7/3*99/4*2998', '10*568/14']中的元素,因为我们要先进行乘除,因此找到包含"/"或"*"的字符串,进行求值,然后进行替换,就可以得到没有乘除的字符串,只包含加减情况:

for num,value in enumerate(calc_list):if "/" in value or "*" in value:"""说明包含乘除,首先进行计算"""mul_div_sign = re.findall("[/*]",value)
        mul_div_list = re.split("[*/]",value)
        print(mul_div_sign)
        print(mul_div_list)
Copy after login

    运算结果如下:

    ['*', '/']
  ['2', '5', '-3']
  ['/', '*', '/', '*']
  ['7', '3', '99', '4', '2998']
  ['*', '/']
  ['10', '568', '14']

    我们得到了运算符和里面的数字,现在只要判断乘除号,然后就可以利用前面一个乘以后面一个进行计算了。如下:

    7、乘除计算:

 1 for num,value in enumerate(calc_list): 2     if "/" in value or "*" in value: 3         """说明包含乘除,首先进行计算""" 4         mul_div_sign = re.findall("[/*]",value) 5         mul_div_list = re.split("[*/]",value) 6         '''接下来,我们计算乘除的情况,首先我们要遍历乘除,因为要进行元素递乘''' 7         res = None 8         for e_index,e_value in enumerate(mul_div_list): 9             if res:10                 if mul_div_sign[e_index-1] == "/":11                     res /= float(e_value)12                 elif mul_div_sign[e_index-1] == "*":13                     res *= float(e_value)14             else:15                 res = float(e_value)      #如果不存在,就生成一个新的,但是我们定义的是不存在的情况,因此肯定是先生成一个数,然后在进行计算16         calc_list[num] = res17     else:18         pass19 20 print(calc_list)21 print(calc_sign)
Copy after login

    运行结果如下:

    ['-9', -3.3333333333333335, 173134.50000000003, 405.7142857142857]
  ['-', '+', '+']

    上述代码,我们进行了乘除的运算,让运算里面不在存在乘除,只需要进行加减运算即可。

    可以看见,我们运算之后,只剩下了加减,这样,我们就可以利用列表的元素和符号进行加减运算。

    8、加减运算:

 1 '''进行加减运算''' 2 result = None 3 for k_index,k_value in enumerate(calc_list): 4     if result: 5         if calc_sign[k_index-1] == "+": 6             result += float(k_value) 7         elif calc_sign[k_index-1] == '-': 8             result -= float(k_value) 9     else:10         result = float(k_value)11 print("result:",result)
Copy after login

    运行如下:

    result: 173534.54761904766

    9、上面,我们得到了运算的结果,然后只需要替换内存括号的内容即可,这样一层一层替换,最终只会剩下没有括号的运算,这个时候,我们在这行这个函数,就能得到最终的结果。

    知识点:

    (1):

<span style="font-family: 宋体; font-size: 16px">result = <span style="color: #000080">None<br></span><span style="color: #000080">for </span><span style="background-color: #ffe4ff">k_index</span>,k_value <span style="color: #000080">in </span><span style="color: #000080">enumerate</span>(calc_list):</span><br><span style="font-family: 宋体; font-size: 16px">    <span style="color: #000080">if </span>result:</span><br><span style="font-family: 宋体; font-size: 16px">        <span style="color: #000080">if </span>calc_sign[<span style="background-color: #e4e4ff">k_index</span>-<span style="color: #0000ff">1</span>] == <span style="color: #008080">"+"</span>:</span><br><span style="font-family: 宋体; font-size: 16px">            result += <span style="color: #000080">float</span>(k_value)</span><br><span style="font-family: 宋体; font-size: 16px">        <span style="color: #000080">elif </span>calc_sign[<span style="background-color: #e4e4ff">k_index</span>-<span style="color: #0000ff">1</span>] == <span style="color: #008080">'-'</span>:</span><br><span style="font-family: 宋体; font-size: 16px">            result -= <span style="color: #000080">float</span>(k_value)</span><br><span style="font-family: 宋体; font-size: 16px">    <span style="color: #000080">else</span>:</span><br><span style="font-family: 宋体; font-size: 16px">        result = <span style="color: #000080">float</span>(k_value)</span>
Copy after login

    上述代码中,体现了一个思想,由于我们想实现的是前一个数字加上后一个数字,但是没有直接的方法,这个时候,我们就可以先定义一个空值,然后对这个值进行判断,其实判断的目的就是为了给这个变量赋值,赋值就是列表的第一个元素,这样我们就能实现列表中元素每次循环都进行叠加或叠减。这个思想很好。当不存在,想让它存在的时候,就先定义一个空值进行判断,判断之后在进行赋值。赋值之后,相当于result等于元素的第一个值,并且元素下一次循环也是从第二个值开始,列表的长度索引也没有超标。

    2、正则表达式的利用,re(regular的缩写):

    ^表示非,"\"表示转义,就是让表示字符本身的含义,+代表一个或多个

    "\(.[^()]+\)"代表匹配括号,括号中间是包含任意多个不是()的元素,也就是匹配最内层的括号。

    3、字符串的replace()方法,就把字符串进行查找替换,str.replace(old,new),正则中字符串findall()查找元素中所有的正则表达式的值,放在一个列表中;re.split()字符串的分割,按照某个正则字符串进行分割。

The above is the detailed content of Implement an instance of a calculator. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template