これが重複していたらごめんなさい。私は私の質問を少し言い直そうと思いました。
正規表現を使用して数式を評価するにはどうすればよいですか? eval 関数を使用しない場合。
式の例:
math1 = "1+1"
math2 = "3+2-1"
例で示したように、式の可変数の数値に対して機能するようにしたいと思います。
これは少し遅れていますが、任意の数式を評価するための gem を作成しました (内部で eval を使用していません): https://github.com/rubysolo/dentaku
これは本当に厄介です…</p>
math2 = "12+3-4"
head, *tail = math2.scan(/(?<digits>\d+)(?<op>[\+\-\*\/])?/)
.map{|(digits,op)|
[digits.to_i,op]
}
.reverse
tail.inject(head.first){|sum,(digits,op)|
op.nil? ?
digits :
digits.send(op,sum)
}
# => 11
ただし、パーサーを検討する必要があります。
加算と減算の場合、これは機能するはずです
(?:(/d+)([-+]))+(/d+)
これの意味は:
個々の数字と記号はそれぞれグループ 1..n でキャプチャされることに注意してください。
したがって、評価するには、キャプチャ 1 と 3 を取得し、キャプチャ 2 の符号を適用します。次に、キャプチャ 4 の符号 (存在する場合) を前の結果とキャプチャ 5 の数値 (キャプチャ 4 が存在する場合は存在する必要があります) に適用します。等々...
したがって、擬似コードで評価するには:
i=1
result=capture(i)
loop while i <= (n-2) (where n is the capture count):
If capture(i+1) == "-" // is subtraction
result = result - capture(i+2)
Else // is addition
result = result + capture(i+2)
End if
i = i + 2
End while
これは、左から右への結合性に依存しているため、提供した例のように単純な加算と減算でのみ機能します。他の人が示唆しているように、たとえば、正しい (深さ優先?) 順序で評価できるノードのツリーを構築するなど、より複雑なものを適切に解析する必要があるでしょう。