控制台计算器支持负数运算报ArgumentOutOfRangeException如何解决?
问题根因
你当前的拆分逻辑没有区分作为负数前缀的负号和作为二元运算符的减号,所有-字符都被当成减法运算符处理,直接用Split方式拆分数字和运算符会导致两者数量不匹配:
以你输入的-90 - 5 =为例,预处理去空后得到字符串-90-5:
- 按运算符拆分得到
["", "90", "5"],去空后数字列表仅2个元素 - 按数字拆分得到
["-", "-"],运算符列表有2个元素
运算符数量比数字数量多1,计算第二个运算符时访问numbersOfExpression[i+1]就会触发下标越界异常。
修复方案
不用引入第三方组件,把原有粗暴的Split拆分逻辑替换为逐字符遍历解析,即可准确区分负号和减号,修改后的完整代码如下:
public static class Parser { private static readonly char[] ValidOperators = "/*+-".ToCharArray(); private static readonly int[] OperatorPriorities = new[] {0, 0, 1, 1}; public static ResultExpressionValue GetUserExpression(string inputData) { // 预处理:去空格、去掉末尾的等号 var userExpression = inputData.Replace(" ", "").TrimEnd('='); var numbersOfExpression = new List<double>(); var expressionOperators = new List<char>(); string currentNumber = string.Empty; // 逐字符遍历解析,区分负号和减号 for (int i = 0; i < userExpression.Length; i++) { char c = userExpression[i]; // 数字、小数点直接加入当前数字缓存 if (char.IsDigit(c) || c == '.') { currentNumber += c; } // 命中运算符 else if (ValidOperators.Contains(c)) { // 两种情况判定为负号而非减号:1. 字符串开头 2. 前一个字符也是运算符 if (currentNumber.Length == 0 && c == '-') { currentNumber += c; } // 正常二元运算符 else { numbersOfExpression.Add(double.Parse(currentNumber)); expressionOperators.Add(c); currentNumber = string.Empty; } } } // 加入最后一个数字 numbersOfExpression.Add(double.Parse(currentNumber)); // 原有运算逻辑保持不变 var operators = new List<char>(); foreach (int priority in OperatorPriorities.Distinct()) { for (int i = 0; i < OperatorPriorities.Length; i++) { if (OperatorPriorities[i] == priority) { operators.Add(ValidOperators[i]); } } for (int i = 0; i < expressionOperators.Count; i++) { if (operators.Contains(expressionOperators[i])) { numbersOfExpression[i] = AddsTheResultOfTheParsedNumbers(numbersOfExpression[i], numbersOfExpression[i + 1], expressionOperators[i]); numbersOfExpression.RemoveAt(i + 1); expressionOperators.RemoveAt(i); i--; } } } if (Double.IsPositiveInfinity(numbersOfExpression[0])) { throw new DivideByZeroException( $"{Environment.NewLine}Division by zero is not possible{Environment.NewLine}"); } return new ResultExpressionValue(numbersOfExpression); } private static double AddsTheResultOfTheParsedNumbers(double left, double right, char op) => op switch { '*' => left * right, '/' => left / right, '+' => left + right, '-' => left - right, _ => throw new NotSupportedException() }; }
适配场景说明
修改后的代码可支持以下负数相关的运算场景:
- 表达式开头为负数:如
-90 -5 =,计算结果为-95 - 运算符后接负数:如
3 * -4 =、10 - -7 =,计算结果分别为-12、17 - 多负数混合运算:如
-20 + -5 * 3 =,计算结果为-35,如果需要支持括号运算可在此基础上扩展括号解析逻辑即可。
内容的提问来源于stack exchange,提问作者ItachiU
相关产品推荐
相关产品推荐

