Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using System.Globalization;
- using System.Diagnostics;
- namespace rpn
- {
- public class Program
- {
- static void Main(string[] args)
- {
- RPN rpn = new RPN();
- Stopwatch stopwatch = Stopwatch.StartNew();
- for (int i = 0; i < 800000; ++i)
- rpn.Eval("2^3+123.43");
- stopwatch.Stop();
- Console.WriteLine(stopwatch.Elapsed);
- Console.WriteLine("wynik = {0}", rpn.Result);
- Console.ReadKey(true);
- }
- }
- public class RPN
- {
- [StructLayout(LayoutKind.Explicit)]
- private struct Item
- {
- [FieldOffset(0)]
- public byte operatorType;
- [FieldOffset(1)]
- public byte priority;
- [FieldOffset(2)]
- public ushort itemType;
- [FieldOffset(0)]
- public float number;
- }
- public float Result
- {
- get;
- private set;
- }
- private Stack<Item> stack;
- private Queue<Item> queue;
- public void Eval(string data)
- {
- stack = new Stack<Item>();
- queue = new Queue<Item>();
- ToPostfix(data);
- Solve();
- }
- private void ToPostfix(string data)
- {
- Item item = new Item();
- for (int i = 0; i < data.Length;)
- {
- if (char.IsDigit(data[i]))
- {
- int pos = i;
- while (i < data.Length && (char.IsDigit(data[i]) || data[i] == '.')) ++i;
- //item.number = float.Parse(data.Substring(pos, i - pos), CultureInfo.InvariantCulture);
- item.number = atof(data.Substring(pos, i - pos));
- queue.Enqueue(item);
- }
- else
- {
- item.itemType = 0xFFFF;
- item.operatorType = (byte)data[i];
- item.priority = GetOperatorPriority(data[i]);
- while (stack.Count != 0 && item.priority <= stack.Peek().priority)
- queue.Enqueue(stack.Pop());
- stack.Push(item);
- ++i;
- }
- }
- while (stack.Count != 0)
- queue.Enqueue(stack.Pop());
- }
- private void Solve()
- {
- while (queue.Count != 0)
- {
- if (queue.Peek().itemType != 0xFFFF)
- stack.Push(queue.Dequeue());
- else
- {
- float op2 = stack.Pop().number;
- float op1 = stack.Peek().number;
- char op = (char)queue.Dequeue().operatorType;
- Item result = stack.Pop();
- switch (op)
- {
- case '+': result.number = op1 + op2; break;
- case '-': result.number = op1 - op2; break;
- case '*': result.number = op1 * op2; break;
- case '/': result.number = op1 / op2; break;
- case '^': result.number = (float)Math.Pow((double)op1, (double)op2); break;
- }
- stack.Push(result);
- }
- }
- Result = stack.Pop().number;
- }
- private byte GetOperatorPriority(char op)
- {
- if (op == '+' || op == '-')
- return 1;
- else if (op == '*' || op == '/')
- return 2;
- else
- return 3;
- }
- private float atof(string data)
- {
- float sign = 1, value = 0;
- int i = 0;
- while (char.IsWhiteSpace(data[i])) i++;
- if (data[i] == '-')
- {
- sign = -1;
- ++i;
- }
- else if (data[i] == '+')
- ++i;
- while (char.IsDigit(data[i]))
- {
- value = value * 10 + ((byte)data[i] - '0');
- ++i;
- if (i >= data.Length) return sign * value;
- }
- if (data[i] == '.')
- {
- float pow10 = 10;
- ++i;
- while (i < data.Length && char.IsDigit(data[i]))
- {
- value += ((byte)data[i] - '0') / pow10;
- pow10 *= 10;
- ++i;
- }
- }
- return sign * value;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement