まず、数値とアクションの正規表現を強調します。
private const string RegexBr = "\\(([1234567890\\.\\+\\-\\*\\/^%]*)\\)"; // private const string RegexNum = "[-]?\\d+\\.?\\d*"; // private const string RegexMulOp = "[\\*\\/^%]"; // private const string RegexAddOp = "[\\+\\-]"; //
次に、結果の文字列を要素に分割し、それらを再帰的に計算するメソッド:
public static double Parse(string str) { // var matchSk = Regex.Match(str, RegexBr); if (matchSk.Groups.Count > 1) { string inner = matchSk.Groups[0].Value.Substring(1, matchSk.Groups[0].Value.Trim().Length - 2); string left = str.Substring(0, matchSk.Index); string right = str.Substring(matchSk.Index + matchSk.Length); return Parse(left + Parse(inner).ToString(CultureInfo.InvariantCulture) + right); } // var matchMulOp = Regex.Match(str, string.Format("({0})\\s?({1})\\s?({2})\\s?", RegexNum, RegexMulOp, RegexNum)); var matchAddOp = Regex.Match(str, string.Format("({0})\\s?({1})\\s?({2})\\s?", RegexNum, RegexAddOp, RegexNum)); var match = matchMulOp.Groups.Count > 1 ? matchMulOp : matchAddOp.Groups.Count > 1 ? matchAddOp : null; if (match != null) { string left = str.Substring(0, match.Index); string right = str.Substring(match.Index + match.Length); return Parse(left + ParseAct(match).ToString(CultureInfo.InvariantCulture) + right); } // try { return double.Parse(str, CultureInfo.InvariantCulture); } catch (FormatException) { throw new FormatException(string.Format(" '{0}'", str)); } }
最後に、アクションの値を直接計算するメソッドを作成します。
private static double ParseAct(Match match) { double a = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); double b = double.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture); switch (match.Groups[2].Value) { case "+": return a + b; case "-": return a - b; case "*": return a * b; case "/": return a / b; case "^": return Math.Pow(a, b); case "%": return a % b; default: throw new FormatException($" '{match.Value}'"); } }
そのような「異常なプログラミング」がありました。 私はソースコードに完全に何も見当たりません-誰もそれをほとんど必要としません。 ただし、いずれにしても、3つのクラスを作成するのは数秒で完了します。
ご清聴ありがとうございました。