Heim  >  Artikel  >  Backend-Entwicklung  >  Implementieren Sie eine Instanz eines Taschenrechners

Implementieren Sie eine Instanz eines Taschenrechners

PHP中文网
PHP中文网Original
2017-06-20 14:35:471371Durchsuche

Aufgabe: Rechnerentwicklung

  (1) Implementierung der Additions-, Subtraktions-, Multiplikations-, Divisions- und Erweiterungsprioritätsanalyse

 (2) Benutzereingabe1 - 2 * ( (60-30 +(-40/5) * (-9-2*5/-3 + 7 /3*99/4 *2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) und andere ähnliche Formeln müssen Sie die darin enthaltenen Symbole (), +, -, *, / und Formeln analysieren. Nach der Operation Um ein Ergebnis zu erhalten, muss das Ergebnis mit dem übereinstimmen, was ein echter Taschenrechner liefern würde.

Der Code lautet wie folgt:

 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)

Programmablauf:

Allgemeine Idee: Wir wissen, dass Sie das Format der obigen Zeichenfolge berechnen müssen kann die Funktion eval() verwenden, aber hier müssen wir selbst einen Rechner schreiben. Wir wissen, dass die Priorität mathematischer Operationen darin besteht, dass die Klammern die höchste Priorität haben und die Dinge in den Klammern zuerst bedient werden, also ist unsere Idee eine Übereinstimmung Setzen Sie die Klammern in den Speicher und führen Sie dann die Operation aus. Nachdem Sie den Inhalt der Klammern im Speicher abgeglichen haben, berechnen wir und verwenden dann den berechneten Wert, um den Wert an der ursprünglichen Position in der Zeichenfolge zu ersetzen, bis keine Klammerposition mehr in der Zeichenfolge vorhanden ist Dieses Mal befolgen wir die normale Reihenfolge der Berechnungen.

1. Regulärer Abgleich, zuerst die Speicherklammern finden; der Code lautet wie folgt:

Formel = '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())

Die Laufergebnisse sind wie folgt:

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

Oben haben wir die aus dem Speicher extrahierte Zeichenfolge beobachtet. Es ist ersichtlich, dass viele Leerzeichen in der Zeichenfolge geändert werden müssen Außerdem sind während des Berechnungsprozesses keine Klammern erforderlich. Entfernen Sie diese daher ebenfalls.

2. Entfernen Sie Leerzeichen und Klammern;

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

läuft wie folgt:

-9-2*5/-3+7 / 3*99/4*2998+10*568/14
3. Nachdem wir die obige Zeichenfolge erhalten haben und die Operation Schicht für Schicht ausführen, können +-, -+, ++, -- usw. erscheinen . Da es sich nun um die erste Ebene handelt, ist das Problem nicht erkennbar. Wenn der Speicher nach der Operation eine negative Zahl erhält, wird er angezeigt +-, - usw. Auch wenn es nicht funktioniert, muss es verarbeitet werden.

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

Die Operation ist wie folgt:

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

4. Wenn die obige Verarbeitung abgeschlossen ist, beginnt die Berechnung offiziell. Wir wissen, dass die Berechnung zuerst die Multiplikation und Division berechnen muss, da Multiplikation und Division das haben höchste Priorität, da Multiplikation und Division zuerst gefunden werden müssen und Addition und Subtraktion nach Abschluss der Berechnung berechnet werden können

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

läuft wie folgt:

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

Wir haben das Berechnungsliste und Operationssymbole, ['', '9', '2*5/', '3', '7/3*99/4*2998', '10*568/14']Es gibt auch Probleme im Inneren. Erstens ist das erste Element der Liste „“ leer, was bedeutet, dass diese Situation nur dann auftritt, wenn ihr ein „-“-Zeichen vorangestellt ist, und es gibt 2 *5/ , dieser Beschreibung folgt auch eine negative Zahl, die verarbeitet werden muss, bevor die Budgetberechnung durchgeführt werden kann. Warum passiert das? Dies liegt daran, dass wir während des Vorgangs „+“ oder „-“ verwenden, um die Zeichenfolge zu teilen. Wenn es sich um eine negative Zahl handelt, wird die Vorderseite um eins geteilt wird einen Fehler in unserer Berechnung verursachen, da wir ihn ändern müssen.

5. Ändern Sie die obige 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)
für Index, e in enumerate(calc_list):
 if e.endswith("/") oder e.endswith("*"):
'''Zeigt an, dass das, was folgt, eine negative Zahl ist und korrigiert werden muss'''
          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)

Führen Sie Folgendes aus:

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 : ['-', '+', '+']

Wie Sie oben sehen können, haben wir die Korrektur in zwei Strichen vorgenommen Beim ersten Mal haben wir das Leerzeichen „“ am Anfang des Elementarproblems entfernt; beim zweiten Mal wird der Fall der Multiplikation und Division gefolgt von negativen Zahlen aufgeworfen

    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()字符串的分割,按照某个正则字符串进行分割。

Das obige ist der detaillierte Inhalt vonImplementieren Sie eine Instanz eines Taschenrechners. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn