提问人:Fabricio Leinat 提问时间:8/11/2023 最后编辑:Mike 'Pomax' KamermansFabricio Leinat 更新时间:8/13/2023 访问量:45
Math Expression Evaluator 中的十进制转换问题
Problem with decimal convertion in Math Expression Evaluator
问:
我正在 C# 中实现一个数学表达式计算器,但我无法使用十进制数,例如,如果我输入“3.4”,程序会将其视为“34”。如果使用像“3,4”这样的昏迷,问题是一样的。
static void EvaluateInput(string input)
{
string[] parts = input.Split('=');
if (parts.Length == 2)
{
string variableName = parts[0].Trim();
if (IsValidVariableName(variableName))
{
string expression = parts[1].Trim();
double result = SolveExpression(expression);
variables[variableName] = SolveExpression(expression);
lastResult = result;
Console.WriteLine($"{variableName} = {result}");
}
else
{
Console.WriteLine("Invalid variable name. Use lowercase letters.");
}
}
else
{
double result = SolveExpression(input);
lastResult = result;
Console.WriteLine($" = {result}");
}
}
static bool IsValidVariableName(string variableName)
{
return !string.IsNullOrEmpty(variableName) && variableName.Length == 1 && char.IsLower(variableName[0]);
}
static double SolveExpression(string expression)
{
expression = expression.Replace(',', '.');
foreach (var constant in constants)
{
expression = expression.Replace(constant.Key, constant.Value.ToString(CultureInfo.InvariantCulture));
}
expression = Regex.Replace(expression, @"(?<=[^\d\.])-", "-");
expression = Regex.Replace(expression, @"(?<=\d)-", " -");
string[] tokens = TokenizeExpression(expression);
Stack<string> operators = new Stack<string>();
Stack<double> values = new Stack<double>();
foreach (string token in tokens)
{
if (double.TryParse(token, out double number))
{
values.Push(number);
}
else if (IsValidVariableName(token))
{
if (variables.ContainsKey(token))
{
values.Push(variables[token]);
}
else
{
throw new InvalidOperationException($"Undefined variable: {token}");
}
}
else if (IsOperator(token))
{
while (operators.Count > 0 && Priority(operators.Peek()) >= Priority(token))
{
if (operators.Peek() == "(")
break;
if (values.Count >= 2)
{
double val2 = values.Pop();
double val1 = values.Pop();
string op = operators.Pop();
values.Push(ApplyOperator(op, val1, val2));
}
else
{
break;
}
}
operators.Push(token);
}
else if (token == "(")
{
operators.Push(token);
}
else if (token == ")")
{
while (operators.Peek() != "(")
{
double val2 = values.Pop();
double val1 = values.Pop();
string op = operators.Pop();
values.Push(ApplyOperator(op, val1, val2));
}
operators.Pop();
}
}
while (operators.Count > 0)
{
if (values.Count >= 2)
{
double val2 = values.Pop();
double val1 = values.Pop();
string op = operators.Pop();
values.Push(ApplyOperator(op, val1, val2));
}
else
{
break;
}
}
return values.Count > 0 ? values.Pop() : 0;
}
static string[] TokenizeExpression(string expression)
{
List<string> tokens = new List<string>();
string currentToken = "";
for (int i = 0; i < expression.Length; i++)
{
char c = expression[i];
if (char.IsDigit(c) || c == '.' || c == ',')
{
currentToken += c;
}
else
{
if (!string.IsNullOrEmpty(currentToken))
{
if (double.TryParse(currentToken.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out double parsedNumber))
{
tokens.Add(parsedNumber.ToString(CultureInfo.InvariantCulture));
}
else
{
tokens.Add(currentToken);
}
currentToken = "";
}
if (IsOperator(c.ToString()) || c == '(' || c == ')')
{
tokens.Add(c.ToString());
}
else if (char.IsLetter(c))
{
currentToken = c.ToString();
}
}
}
if (!string.IsNullOrEmpty(currentToken))
{
if (double.TryParse(currentToken.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out double parsedNumber))
{
tokens.Add(parsedNumber.ToString(CultureInfo.InvariantCulture));
}
else
{
tokens.Add(currentToken);
}
}
return tokens.ToArray();
}
static bool IsOperator(string token)
{
return token == "+" || token == "-" || token == "*" || token == "/" || token == "^";
}
static int Priority(string op)
{
if (op == "^")
return 3;
if (op == "*" || op == "/")
return 2;
if (op == "+" || op == "-")
return 1;
return 0;
}
static double ApplyOperator(string op, double a, double b)
{
switch (op)
{
case "+": return a + b;
case "-": return a - b;
case "*": return a * b;
case "/": return a / b;
case "^": return Math.Pow(a, b);
default: throw new ArgumentException($"Invalid operator: {op}");
}
}
我试图强制代码使用“en-US”全球化,但我没有成功。我还尝试了差异解析,将字符串转换为浮点数,也没有成功
答:
0赞
Bart Kiers
8/11/2023
#1
而不是做:
if (double.TryParse(token, out double number))
{
values.Push(number);
}
试试这个:
if (new Regex(@"\d+(\.\d+)?").IsMatch(token))
{
values.Push(double.Parse(token, CultureInfo.InvariantCulture));
}
其他 s 可能也需要更改。TryParse
下一个: 解析(抓取)时代替数字
评论