ホームページ  >  記事  >  バックエンド開発  >  四則演算を徹底分析

四則演算を徹底分析

高洛峰
高洛峰オリジナル
2017-03-26 16:50:372257ブラウズ

文字列の算術を計算するには?

マッチングに

正規表現を使用する場合、それは少し考えられません。一般的な考え方は再帰を設計することですが、Pythonでは再帰を使用することは強く推奨されません。再帰だけではないためです

深さ制限 (通常は 1000 スタック フレーム) があり、末尾再帰的最適化はサポートされません。

最も簡単な方法は、最初に式を接頭辞式に変換し、次に接頭辞式を通じて結果を計算することです。

接頭辞式 (

演算子の前) はポーランド式とも呼ばれ、対応する接尾辞式 (演算子の後ろ) は逆ポーランド式とも呼ばれます。私たちの生活には、

一般的な大きな式中置式もあります。式は、ほとんどの

プログラミング言語 で使用されます。

中置式を前置式に変換するためのルール:

(1) 2つのスタックを初期化します: 演算子スタックS1と中間結果を格納するスタックS2

(2) 中置式を右から左にスキャンします

(3)オペランドをS2にプッシュする

(4) 演算子に出会ったら、S1スタックの先頭にある演算子の優先度と比較する

: (4-1) S1が先頭の演算子の場合スタックが空であるか、スタックの先頭にある演算子が右括弧 ")" の場合、この演算子はスタックに直接プッシュされます

(4-2) それ以外の場合、優先度がそれより高いか等しい場合スタックの一番上にある演算子の場合、その演算子もスタックにプッシュされます

、それ以外の場合は、S1のスタックの一番上にある演算子をポップしてS2にプッシュします

。再度(4-1)に戻り、S1のスタックの先頭にある新しい演算子と比較します

( 5) 括弧があった場合:

(5-1) 右括弧「)」の場合、 S1 を直接プッシュします

(5-2) 左括弧「(」の場合は、S1 スタックの先頭の操作をシーケンス記号でポップアップし、右括弧に遭遇するまで S2 をプッシュします。

このとき, この括弧のペアを破棄します

(6) 式の左端まで手順(2)~(5)を繰り返します

(7) S1に残っている演算子を1つずつポップしてS2にプッシュします

(8 ) S2 の要素を 1 つずつポップし、結果を中置式に対応する前置式にします。つまり、括弧を削除します。接頭辞式に変換します

def mid_to_prev(expressions: str):
    priority = {  # 运算符的优先级
        "/": 1,
        "//": 1,
        "*": 1,
        "%": 1,
        "+": 0,
        "-": 0,
        "**": 2 }
    expression_list = expressions.split() # 
    number_stack = [] # 数字栈
    symbol_stack = [] # 运算符栈
    for x in expression_list[::-1]:
        if x.isdigit():             
            number_stack.insert(0, x)  # 如果是整数直接存进去
        else:
            if x == '(':         # 如果是 ( 弹出运算符栈中的运算符直到遇到 ( 
                pop_symbol = symbol_stack[0]
                while pop_symbol != ')':
                    pop_symbol = symbol_stack.pop(0)
                    number_stack.insert(0, pop_symbol)
                    pop_symbol = symbol_stack[0]
                else:
                    symbol_stack.pop(0)
            elif len(symbol_stack) == 0 or symbol_stack[0] == ')' or x == ')' or priority[x] >= priority[symbol_stack[0]]:
                symbol_stack.insert(0, x)  # 当符号栈为空 或者 遇到 ) 或者栈顶的符号是 ) 或者优先级大于等于符号栈顶的运算符优先级 直接存进去

            elif priority[x] < priority[symbol_stack[0]]:  # 优先级小于符号栈顶元素的时候
                while symbol_stack[0] != &#39;)&#39; and priority[x] < priority[symbol_stack[0]]:
                    number_stack.insert(0, symbol_stack.pop(0))
                else:
                    symbol_stack.insert(0, x)
    else:
        while len(symbol_stack) != 0:
            number_stack.insert(0, symbol_stack.pop(0))
    return number_stack

例:

変換された接頭辞式スタックを操作するのは簡単です

(1) 新しいリストを初期化します

四則演算を徹底分析(2) 接頭辞式リストを右から左にたどって、数値を入力し、それを新しいリストに保存します

(3) 演算子に遭遇したら、新しいリストの最初の 2 つの数値をポップアップ表示し、演算を実行します。結果はプレフィックスまで新しいリストに保存されます

(4)現時点では、新しいリストには要素が 1 つだけあり、これが最終結果です

def calc(number1,number2,calc): # 两个数运算
    if calc == &#39;/&#39;:
        return number1 / number2
    elif calc == &#39;*&#39;:
        return number1 * number2
    elif calc == &#39;//&#39;:
        return number1 // number2
    elif calc == &#39;**&#39;:
        return number1 ** number2
    elif calc == &#39;%&#39;:
        return number1 % number2
    elif calc == &#39;+&#39;:
        return number1 + number2
    elif calc == &#39;-&#39;:
        return number1 - number2

合計結果が得られます:

def operation(stack_list:list):
    number = []
    for x in stack_list[::-1]:
        if x.isdigit():
            number.insert(0, x)
        else:
            first = number.pop(0)
            second = number.pop(0)
            tmp = calc(int(first),int(second), x)
            number.insert(0,tmp)
    return number.pop(0)

例:

前のプレフィックスの結果。式:

検証結果は正しいです四則演算を徹底分析

注: 式はスペースで区切る必要があります

四則演算を徹底分析 整数のみと一致します

以上が四則演算を徹底分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。