附上参考文章链接:https://blog.csdn.net/qq_34831781/article/details/80104219
本人整合修复一些bug后的代码

1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Text;
5
6 // 解析计算字符串公式
7 namespace CalcuStrFormula
8 {
9 // 处理类
10 class Handler
11 {
12 private Stack _complexNumberStack = new Stack();
13 private Stack _operatorStack = new Stack();
14 private Parser _parser = new Parser();
15 private Operators _operators = new Operators();
16
17 private static Handler _instance;
18 public static Handler instance
19 {
20 get
21 {
22 if (_instance == null)
23 {
24 _instance = new Handler();
25 }
26 return _instance;
27 }
28 }
29
30 public ComplexNumber Process(string inputString)
31 {
32 _complexNumberStack.Clear();
33 _operatorStack.Clear();
34
35 Queue<object> queue = _parser.Parse(inputString);
36 ComplexNumber complexNumber = null;
37 char op, topOp;
38 int count = queue.Count;
39 for (int i = 0; i < count; i++)
40 {
41 object obj = queue.Dequeue();
42 if (obj is char)
43 {
44 op = (char)obj;
45 if (_operatorStack.Count == 0)
46 {
47 _operatorStack.Push(op);
48 }
49 else
50 {
51 topOp = (char)_operatorStack.Peek();
52 if (op == '(')
53 {
54 _operatorStack.Push(op); // 左括号直接压入。不判断栈顶
55 }
56 else if (op == ')')
57 {
58 // 右括号压入前观察栈顶,若栈顶是左括号,则弹出栈顶的左括号
59 // 否则弹出栈顶运算符,从数栈中弹出操作数进行运算,并将结果重新压入数栈,直到遇到左括号
60 while ((topOp = (char)_operatorStack.Pop()) != '(')
61 {
62 ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
63 ComplexNumber c2 = null; // 符号左边数
64 if (_operators.IsTwoNumOperator(topOp))
65 {
66 c2 = (ComplexNumber)_complexNumberStack.Pop();
67 }
68 ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
69 _complexNumberStack.Push(c3);
70 }
71 }
72 else if (_operators.ComparePriority(topOp, op) <= 0)
73 {
74 // 若即将压入的运算符不是括号,则比较栈顶运算符和即将压入的运算符的优先级
75 // 如果栈顶优先级高,则将栈顶运算符取出运算,直到栈顶优先级不大于其。
76 while (_operatorStack.Count != 0 && _operators.ComparePriority((char)_operatorStack.Peek(), op) <= 0)
77 {
78 topOp = (char)_operatorStack.Pop();
79 ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
80 ComplexNumber c2 = null; // 符号左边数
81 if (_operators.IsTwoNumOperator(topOp))
82 {
83 c2 = (ComplexNumber)_complexNumberStack.Pop();
84 }
85 ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
86 _complexNumberStack.Push(c3);
87 }
88 _operatorStack.Push(op);
89 }
90 else
91 {
92 _operatorStack.Push(op);
93 }
94 }
95 }
96 else if (obj is ComplexNumber)
97 {
98 complexNumber = (ComplexNumber)obj;
99 _complexNumberStack.Push(complexNumber);
100 }
101
102 if (queue.Count == 0)
103 {
104 while (_operatorStack.Count != 0)
105 {
106 topOp = (char)_operatorStack.Pop();
107 ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
108 ComplexNumber c2 = null; // 符号左边数
109 if (_operators.IsTwoNumOperator(topOp))
110 {
111 c2 = (ComplexNumber)_complexNumberStack.Pop();
112 }
113 ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
114 _complexNumberStack.Push(c3);
115 }
116 }
117 }
118
119 return (ComplexNumber)_complexNumberStack.Pop();
120 }
121 }
122
123 // 3+4i解析成Queue包含 3, +, 4i
124 public class Parser
125 {
126 private Operators _operators = new Operators();
127
128 public Queue<object> Parse(string input)
129 {
130 input = input.Replace(" ", "");
131 if (input.StartsWith("-")) input = '0' + input;
132
133 char[] arr = input.ToCharArray();
134 Queue<char> queueChar = new Queue<char>();
135 foreach (char x in arr)
136 {
137 queueChar.Enqueue(x);
138 }
139 Queue<object> queueResult = ParseStringQueue(queueChar);
140 return queueResult;
141 }
142
143 // 传入字符串队列,返回封装好的队列。
144 // ComplexNumber对象或char类型运算符各占用一个结点
145 private Queue<object> ParseStringQueue(Queue<char> queue)
146 {
147 Queue<object> secondQ = new Queue<object>();
148 char c;
149 StringBuilder sb = null;
150 string temp;
151 int count = queue.Count;
152 bool flag = false; // false表示允许创建新SB对象进行缓存数字字符串
153 for (int i = 0; i < count; i++)
154 {
155 c = queue.Dequeue();
156 if (!_operators.Contains(c))
157 {
158 // 如果扫描到的不是运算符,则将其加入到buffer尾部
159 if (!flag)
160 {
161 flag = true;
162 sb = new StringBuilder();
163 }
164 sb.Append(c);
165 }
166 if (_operators.Contains(c) || queue.Count == 0)
167 {
168 // 如果扫描到的是运算符,则将缓冲区中的串加入队尾
169 if (sb != null && flag == true)
170 {
171 temp = sb.ToString();
172 try
173 {
174 if (temp.EndsWith("i"))
175 {
176 if (temp.Length == 1)
177 {
178 secondQ.Enqueue(new ComplexNumber(0, 1));
179 }
180 else
181 {
182 // i前有数字则开出数字部分。
183 temp = temp.Substring(0, temp.Length - 1);
184 secondQ.Enqueue(new ComplexNumber(0, double.Parse(temp)));
185 }
186 }
187 else
188 {
189 secondQ.Enqueue(new ComplexNumber(double.Parse(temp), 0));
190 }
191 sb = null;
192 flag = false;
193 }
194 catch (Exception e)
195 {
196 UnityEngine.Debug.Log("Error " + e.ToString());
197 }
198 }
199 // 如果是运算符,则最后将运算符放入队。
200 if (_operators.Contains(c))
201 {
202 secondQ.Enqueue(c);
203 }
204 }
205 }
206
207 return secondQ;
208 }
209 }
210
211 // 复数类,提供实数域虚数域,getset方法,加减乘除以及toString()方法
212 class ComplexNumber
213 {
214 private double _realPart; // 实数部分
215 private double _imaginPart; // 虚数部分
216
217 public ComplexNumber()
218 {
219 _realPart = 0.0;
220 _imaginPart = 0.0;
221 }
222 public ComplexNumber(double r, double i)
223 {
224 _realPart = r;
225 _imaginPart = i;
226 }
227 public ComplexNumber(ComplexNumber c)
228 {
229 _realPart = c.GetRealPart();
230 _imaginPart = c.GetImaginaryPart();
231 }
232
233 // get,set方法
234 public double GetRealPart()
235 {
236 return _realPart;
237 }
238 public double GetImaginaryPart()
239 {
240 return _imaginPart;
241 }
242 public void SetRealPart(double d)
243 {
244 _realPart = d;
245 }
246 public void SetImaginaryPart(double d)
247 {
248 _imaginPart = d;
249 }
250
251 // 加
252 public ComplexNumber ComplexAdd(ComplexNumber c)
253 {
254 return new ComplexNumber(_realPart + c.GetRealPart(), _imaginPart + c.GetImaginaryPart());
255 }
256 public ComplexNumber ComplexAdd(double c)
257 {
258 return new ComplexNumber(_realPart + c, _imaginPart);
259 }
260 // 减
261 public ComplexNumber ComplexMinus(ComplexNumber c)
262 {
263 return new ComplexNumber(_realPart - c.GetRealPart(), _imaginPart - c.GetImaginaryPart());
264 }
265 public ComplexNumber ComplexMinus(double c)
266 {
267 return new ComplexNumber(_realPart - c, _imaginPart);
268 }
269 // 乘
270 public ComplexNumber ComplexMulti(ComplexNumber c)
271 {
272 return new ComplexNumber(
273 _realPart * c.GetRealPart()
274 - _imaginPart * c.GetImaginaryPart(),
275 _realPart *
276 c.GetImaginaryPart()
277 + _imaginPart *
278 c.GetRealPart());
279 }
280 public ComplexNumber ComplexMulti(double c)
281 {
282 return new ComplexNumber(_realPart * c, _imaginPart * c);
283 }
284 // 除
285 public ComplexNumber ComplexDivision(ComplexNumber c)
286 {
287 return new ComplexNumber((_realPart * c.GetRealPart() + _imaginPart * c.GetImaginaryPart())
288 / (c.GetRealPart() * c.GetRealPart() + c.GetImaginaryPart() * c.GetImaginaryPart())
289 , (_imaginPart * c.GetRealPart() - _realPart * c.GetImaginaryPart())
290 / (c.GetRealPart() * c.GetRealPart() + c.GetImaginaryPart() * c.GetImaginaryPart()));
291 }
292 public ComplexNumber ComplexDivision(double c)
293 {
294 return new ComplexNumber(_realPart / c, _imaginPart / c);
295 }
296 // 幂
297 public ComplexNumber ComplexPow(ComplexNumber c)
298 {
299 int pow;
300 if (int.TryParse(c.GetRealPart().ToString(), out pow))
301 {
302 ComplexNumber origin = new ComplexNumber(this);
303 ComplexNumber multi = new ComplexNumber(this);
304 for (int i = 0; i < pow - 1; i++)
305 {
306 origin = origin.ComplexMulti(multi);
307 }
308 return origin;
309 }
310 else
311 {
312 return ComplexPow(c.GetRealPart());
313 }
314 }
315 public ComplexNumber ComplexPow(double c)
316 {
317 return new ComplexNumber(Math.Pow(_realPart, c), 0.0);
318 }
319 // 最小值
320 public ComplexNumber ComplexMinimum(ComplexNumber c)
321 {
322 if (_realPart <= c.GetRealPart()) return this;
323 return c;
324 }
325 // 最大值
326 public ComplexNumber ComplexMaximum(ComplexNumber c)
327 {
328 if (_realPart >= c.GetRealPart()) return this;
329 return c;
330 }
331 // 转int
332 public ComplexNumber ToFloorInt()
333 {
334 _realPart = Math.Floor(_realPart);
335 return this;
336 }
337
338 public override string ToString()
339 {
340 return "(" + _realPart + " + " + _imaginPart + " i" + ")";
341 }
342 }
343
344 // 操作符类
345 class Operators
346 {
347 private char[][] _signOperator;
348
349 public Operators()
350 {
351 // 从上到下,优先级由高到低
352 _signOperator = new char[4][];
353 _signOperator[0] = new char[4];
354 _signOperator[0][0] = '^';
355 _signOperator[0][1] = 's'; // 最小值
356 _signOperator[0][2] = 'b'; // 最大值
357 _signOperator[0][3] = 'i'; // int值
358 _signOperator[1] = new char[2];
359 _signOperator[1][0] = '*';
360 _signOperator[1][1] = '/';
361 _signOperator[2] = new char[2];
362 _signOperator[2][0] = '+';
363 _signOperator[2][1] = '-';
364 _signOperator[3] = new char[2];
365 _signOperator[3][0] = '(';
366 _signOperator[3][1] = ')';
367 }
368
369 // 比较操作符优先级
370 public int ComparePriority(char firstSign, char secondSign)
371 {
372 int priorityF = 0, priorityS = 0;
373 for (int i = 0; i < _signOperator.Length; i++)
374 {
375 foreach (char x in _signOperator[i])
376 {
377 if (firstSign == x)
378 {
379 priorityF = i;
380 }
381 if (secondSign == x)
382 {
383 priorityS = i;
384 }
385 }
386 }
387
388 return (priorityF - priorityS);
389 }
390
391 // 是否是需要两个参数的操作符
392 public bool IsTwoNumOperator(char op)
393 {
394 if (op == 'i') return false;
395 return true;
396 }
397
398 public bool Contains(char x)
399 {
400 if (x == '(' || x == ')')
401 {
402 UnityEngine.Debug.LogError(x + "为中文字符,请改为英文字符");
403 }
404
405 foreach (char[] arr in _signOperator)
406 {
407 foreach (char y in arr)
408 {
409 if (x == y)
410 {
411 return true;
412 }
413 }
414 }
415 return false;
416 }
417
418 public ComplexNumber Compute(char op, ComplexNumber c1, ComplexNumber c2)
419 {
420 ComplexNumber result = null;
421 switch (op)
422 {
423 case '+': result = c1.ComplexAdd(c2); break;
424 case '-': result = c1.ComplexMinus(c2); break;
425 case '*': result = c1.ComplexMulti(c2); break;
426 case '/': result = c1.ComplexDivision(c2); break;
427 case '^': result = c1.ComplexPow(c2); break;
428 case 's': result = c1.ComplexMinimum(c2); break;
429 case 'b': result = c1.ComplexMaximum(c2); break;
430 case 'i': result = c2.ToFloorInt(); break;
431 }
432 return result;
433 }
434 }
435 }
仓促上传待整理。。。
