问题出在数学表达式求值中的小数转换上。

huangapple go评论186阅读模式
英文:

Problem with decimal convertion in Math Expression Evaluator

问题

我正在使用C#实现一个数学表达式计算器,但无法使用十进制数,例如,如果我输入"3.4",程序会将其视为"34"。如果使用逗号如"3,4",问题也是一样的。

我已经尝试强制代码使用"en-US"的全球化,但没有成功。我还尝试了不同的解析方法,试图将字符串转换为浮点数,但也没有成功。

英文:

I'm implementing a math expression evaluator in C# but I has not able to use decimal numbers, like, if I enter "3.4" the program consider it as "34". The problem is the same if use coma like "3,4".

  1. static void EvaluateInput(string input)
  2. {
  3. string[] parts = input.Split('=');
  4. if (parts.Length == 2)
  5. {
  6. string variableName = parts[0].Trim();
  7. if (IsValidVariableName(variableName))
  8. {
  9. string expression = parts[1].Trim();
  10. double result = SolveExpression(expression);
  11. variables[variableName] = SolveExpression(expression);
  12. lastResult = result;
  13. Console.WriteLine($"{variableName} = {result}");
  14. }
  15. else
  16. {
  17. Console.WriteLine("Invalid variable name. Use lowercase letters.");
  18. }
  19. }
  20. else
  21. {
  22. double result = SolveExpression(input);
  23. lastResult = result;
  24. Console.WriteLine($" = {result}");
  25. }
  26. }
  27. static bool IsValidVariableName(string variableName)
  28. {
  29. return !string.IsNullOrEmpty(variableName) && variableName.Length == 1 && char.IsLower(variableName[0]);
  30. }
  31. static double SolveExpression(string expression)
  32. {
  33. expression = expression.Replace(',', '.');
  34. foreach (var constant in constants)
  35. {
  36. expression = expression.Replace(constant.Key, constant.Value.ToString(CultureInfo.InvariantCulture));
  37. }
  38. expression = Regex.Replace(expression, @"(?<=[^\d\.])-", "-");
  39. expression = Regex.Replace(expression, @"(?<=\d)-", " -");
  40. string[] tokens = TokenizeExpression(expression);
  41. Stack<string> operators = new Stack<string>();
  42. Stack<double> values = new Stack<double>();
  43. foreach (string token in tokens)
  44. {
  45. if (double.TryParse(token, out double number))
  46. {
  47. values.Push(number);
  48. }
  49. else if (IsValidVariableName(token))
  50. {
  51. if (variables.ContainsKey(token))
  52. {
  53. values.Push(variables[token]);
  54. }
  55. else
  56. {
  57. throw new InvalidOperationException($"Undefined variable: {token}");
  58. }
  59. }
  60. else if (IsOperator(token))
  61. {
  62. while (operators.Count > 0 && Priority(operators.Peek()) >= Priority(token))
  63. {
  64. if (operators.Peek() == "(")
  65. break;
  66. if (values.Count >= 2)
  67. {
  68. double val2 = values.Pop();
  69. double val1 = values.Pop();
  70. string op = operators.Pop();
  71. values.Push(ApplyOperator(op, val1, val2));
  72. }
  73. else
  74. {
  75. break;
  76. }
  77. }
  78. operators.Push(token);
  79. }
  80. else if (token == "(")
  81. {
  82. operators.Push(token);
  83. }
  84. else if (token == ")")
  85. {
  86. while (operators.Peek() != "(")
  87. {
  88. double val2 = values.Pop();
  89. double val1 = values.Pop();
  90. string op = operators.Pop();
  91. values.Push(ApplyOperator(op, val1, val2));
  92. }
  93. operators.Pop();
  94. }
  95. }
  96. while (operators.Count > 0)
  97. {
  98. if (values.Count >= 2)
  99. {
  100. double val2 = values.Pop();
  101. double val1 = values.Pop();
  102. string op = operators.Pop();
  103. values.Push(ApplyOperator(op, val1, val2));
  104. }
  105. else
  106. {
  107. break;
  108. }
  109. }
  110. return values.Count > 0 ? values.Pop() : 0;
  111. }
  112. static string[] TokenizeExpression(string expression)
  113. {
  114. List<string> tokens = new List<string>();
  115. string currentToken = "";
  116. for (int i = 0; i < expression.Length; i++)
  117. {
  118. char c = expression[i];
  119. if (char.IsDigit(c) || c == '.' || c == ',')
  120. {
  121. currentToken += c;
  122. }
  123. else
  124. {
  125. if (!string.IsNullOrEmpty(currentToken))
  126. {
  127. if (double.TryParse(currentToken.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out double parsedNumber))
  128. {
  129. tokens.Add(parsedNumber.ToString(CultureInfo.InvariantCulture));
  130. }
  131. else
  132. {
  133. tokens.Add(currentToken);
  134. }
  135. currentToken = "";
  136. }
  137. if (IsOperator(c.ToString()) || c == '(' || c == ')')
  138. {
  139. tokens.Add(c.ToString());
  140. }
  141. else if (char.IsLetter(c))
  142. {
  143. currentToken = c.ToString();
  144. }
  145. }
  146. }
  147. if (!string.IsNullOrEmpty(currentToken))
  148. {
  149. if (double.TryParse(currentToken.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out double parsedNumber))
  150. {
  151. tokens.Add(parsedNumber.ToString(CultureInfo.InvariantCulture));
  152. }
  153. else
  154. {
  155. tokens.Add(currentToken);
  156. }
  157. }
  158. return tokens.ToArray();
  159. }
  160. static bool IsOperator(string token)
  161. {
  162. return token == "+" || token == "-" || token == "*" || token == "/" || token == "^";
  163. }
  164. static int Priority(string op)
  165. {
  166. if (op == "^")
  167. return 3;
  168. if (op == "*" || op == "/")
  169. return 2;
  170. if (op == "+" || op == "-")
  171. return 1;
  172. return 0;
  173. }
  174. static double ApplyOperator(string op, double a, double b)
  175. {
  176. switch (op)
  177. {
  178. case "+": return a + b;
  179. case "-": return a - b;
  180. case "*": return a * b;
  181. case "/": return a / b;
  182. case "^": return Math.Pow(a, b);
  183. default: throw new ArgumentException($"Invalid operator: {op}");
  184. }
  185. }

I have tried to force the code to use "en-US" globalization but I no success. I also tried difference parses in sense to convert the string to a float number, also not succeed

答案1

得分: 0

尝试这样做:

  1. if (new Regex(@"\d+(\.\d+)?").IsMatch(token))
  2. {
  3. values.Push(double.Parse(token, CultureInfo.InvariantCulture));
  4. }

其他的 TryParse 也可能需要更改。

英文:

Instead of doing:

  1. if (double.TryParse(token, out double number))
  2. {
  3. values.Push(number);
  4. }

try this:

  1. if (new Regex(@"\d+(\.\d+)?").IsMatch(token))
  2. {
  3. values.Push(double.Parse(token, CultureInfo.InvariantCulture));
  4. }

Other TryParses might also need changing.

huangapple
  • 本文由 发表于 2023年8月11日 03:54:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878929.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定