> 백엔드 개발 > 파이썬 튜토리얼 > 계산기 인스턴스 구현

계산기 인스턴스 구현

PHP中文网
풀어 주다: 2017-06-20 14:35:47
원래의
1380명이 탐색했습니다.

과제: 계산기 개발

                                                           기계 개발 시 in in int 계산기 개발

/5) * (-9-2*5/-3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) 등 수식 뒤에는 (), +, -, *, / 기호 및 수식을 직접 구문 분석해야 하며, 연산 후 결과를 얻으십시오. 결과는 실제 계산기에서 얻은 결과와 일치해야 합니다.

코드는 다음과 같습니다.

 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)
로그인 후 복사

프로그램 실행 프로세스:

일반적인 아이디어: 위 문자열의 형식을 계산하려면 eval() 함수를 사용할 수 있지만 여기서는 우리가 직접 계산기를 작성해야 합니다. 그 수학적 연산의 우선순위는 괄호 안의 내용이 가장 먼저 계산된다는 것입니다. 따라서 우리의 아이디어는 메모리 괄호 안의 내용을 일치시킨 후 연산을 수행하는 것입니다. 그런 다음 문자열에 대괄호 위치가 없을 때까지 값이 문자열의 원래 위치에 있는 값을 대체합니다. 이때 일반적인 연산 순서에 따라 계산을 수행합니다.

1. 일반 일치의 경우 먼저 메모리 괄호를 찾으세요. 코드는 다음과 같습니다.

공식 = '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( "(. [.
( -9-2*5 /-3 + 7 /3*99/4*2998 +10 * 568/14 )

위의 메모리에서 추출된 문자열을 관찰한 것을 볼 수 있습니다. 문자열에는 공백이 많아 계산에 영향을 미칩니다. 또한 계산 중에는 괄호가 필요하지 않으므로 괄호를 제거해야 합니다. 2. 공백과 괄호를 제거합니다. Formula_deep = re.sub(

"[() ]",

"",formula_deep) 다음과 같이 실행합니다.

- 9 -2*5/-3+7/3*99/4*2998+10*568/14 3. 위의 문자열을 얻은 후, 레이어별로 연산을 수행하면 +-, -+, + may 이때 +, -- 등의 상황도 처리해야 하는데, 지금은 1단계이므로 연산 후 획득한 메모리가 음수일 경우에는 문제를 볼 수 없다. 이전 괄호를 벗어나면 + -, -가 되며 다른 상황은 현재 불가능하므로 처리해야 합니다

Formula_deep = re.sub("+-",

'-',formula_deep; )

 formula_deep = re.sub(" -+",'-',formula_deep) formula_deep = re.sub("++","+",formula_deep) formula_deep = re.sub(

" --",

'+',formula_deep )


다음과 같이 실행합니다:
-9-2*5/-3+7/3*99/4*2998+10* 568/14
4. 위의 경우 처리가 완료되면 정식으로 계산이 시작됩니다. 곱셈과 나눗셈을 먼저 찾아야 하기 때문에 곱셈과 나눗셈을 먼저 계산해야 한다는 것을 알고 있습니다. 먼저 계산이 완료된 후 덧셈과 뺄셈을 계산할 수 있습니다. calc_sign = re.findall( "[+-]",formula_deep)
 calc_list = re.split("[+-]",formula_deep) 인쇄(calc_list)
 print(calc_sign)

다음과 같이 실행하세요:

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

계산 목록과 연산 기호 ['', '9', '2*5를 얻었습니다. /' , '3', '7/3*99/4*2998', '10*568/14']내부에도 문제가 있습니다. 우선 목록의 첫 번째 요소가 "" 비어 있습니다. 이 상황은 - 숫자로만 발생함을 나타냅니다. 이 상황은 병합되어야 하며, 2*5/도 있습니다. 이 설명 뒤에는 음수가 따라오며 사전 계획 계산이 가능하기 전에 먼저 처리되어야 합니다. 왜 이런 상황이 발생하는 걸까요? 이는 작업 중에 문자열을 분할하기 위해 "+" 또는 "-"를 사용하기 때문입니다. 이로 인해 음수인 경우 처음에는 앞쪽이 하나 비어 있게 분할됩니다. 수정이 필요하기 때문에 계산에 오류가 발생합니다.

5. 위의 작업을 수정하십시오.


UF 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 enum 비율(calc_list ) :      
if e.endswith("/") 또는 e.endswith("*"):
                                                                                                                     L1] = CALC_LIST [색인] + Calc_sign [색인] + Calc_list [색인 + 1]

Del Calc_sign [색인]

"Calc_list:", C alc_list) r proprint ("calc_sign:",calc_sign)
calc_list : [ '-9', '2*5/', '3', '7/3 *99/4*2998', '10*568/14']
계산_부호: ['-', '-', '+', '+']
 calc_list: ['-9', '2*5/ -3', '7/3*99/4*2998', '10*568/14']
 calc_sign: ['-', '+', '+']
에서 알 수 있듯이 위에서는 두 단계로 수정했습니다. 처음에는 "" 빈 요소 문제를 제거했습니다. 두 번째에서는 곱셈과 나눗셈 뒤에 음수가 오는 경우를 제안합니다.

    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)
로그인 후 복사

    运算结果如下:

    ['*', '/']
  ['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)
로그인 후 복사

    运行结果如下:

    ['-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)
로그인 후 복사

    运行如下:

    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>
로그인 후 복사

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

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

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

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

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

위 내용은 계산기 인스턴스 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿