面试题答案
一键面试实现思路
- 解析字符串表达式:使用词法分析和语法分析技术将输入的字符串(如 "3 * x + 2 * y")分解为一个个的标记(token),例如数字、变量名、运算符等,并构建语法树。
- 构建表达式树:根据解析得到的语法树,使用C#的表达式树相关类(如
Expression
类及其派生类)来构建对应的表达式树。 - 优化表达式树:通过常量折叠等优化技术,在表达式树中直接计算可以在编译期确定的常量表达式,减少运行时计算量。例如对于 "3 * 2" 这样的子表达式,在表达式树构建过程中直接计算结果为 6 并替换原表达式。
- 编译和执行表达式树:将优化后的表达式树编译为可执行的委托,通过传递变量的值来执行该委托并得到最终结果。
关键代码片段
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
public class ExpressionEvaluator
{
private Dictionary<string, double> variables = new Dictionary<string, double>();
public void SetVariable(string name, double value)
{
variables[name] = value;
}
public double Evaluate(string expression)
{
// 简单的词法分析,这里仅作示意,实际需更完善
string[] tokens = expression.Split(' ');
Stack<Expression> stack = new Stack<Expression>();
foreach (string token in tokens)
{
if (double.TryParse(token, out double number))
{
stack.Push(Expression.Constant(number));
}
else if (variables.ContainsKey(token))
{
stack.Push(Expression.Constant(variables[token]));
}
else if (token == "+" || token == "-" || token == "*" || token == "/")
{
Expression right = stack.Pop();
Expression left = stack.Pop();
switch (token)
{
case "+":
stack.Push(Expression.Add(left, right));
break;
case "-":
stack.Push(Expression.Subtract(left, right));
break;
case "*":
stack.Push(Expression.Multiply(left, right));
break;
case "/":
stack.Push(Expression.Divide(left, right));
break;
}
}
}
Expression finalExpression = stack.Pop();
// 常量折叠优化,实际可更完善
LambdaExpression lambda = Expression.Lambda(finalExpression);
Delegate compiled = lambda.Compile();
return (double)compiled.DynamicInvoke();
}
}
使用示例:
class Program
{
static void Main()
{
ExpressionEvaluator evaluator = new ExpressionEvaluator();
evaluator.SetVariable("x", 5);
evaluator.SetVariable("y", 10);
double result = evaluator.Evaluate("3 * x + 2 * y");
Console.WriteLine(result);
}
}