MariuszM

RPNcalculator.cs

Aug 23rd, 2025
496
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.58 KB | None | 0 0
  1. using System;
  2. using System.Globalization;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5.  
  6. class Program
  7. {
  8.     private static readonly CultureInfo Culture = new CultureInfo("pl-PL");
  9.    
  10.     static List<string> Tokenize(string expression, Dictionary<string, int> opMap, List<string> functions, Dictionary<string, double> constants)
  11.     {
  12.         List<string> tokens = new List<string>();
  13.         string temp = "";
  14.         for (int i = 0; i < expression.Length; ++i)
  15.         {
  16.             char c = expression[i];
  17.             if (c == ' ') continue;
  18.  
  19.             // Obsługa stałych matematycznych
  20.             if (char.IsLetter(c) && constants.ContainsKey(c.ToString()))
  21.             {
  22.                 if (!string.IsNullOrEmpty(temp))
  23.                 {
  24.                     tokens.Add(temp);
  25.                     temp = "";
  26.                 }
  27.                 tokens.Add(c.ToString());
  28.                 continue;
  29.             }
  30.  
  31.             // Obsługa przecinków w funkcjach wieloargumentowych
  32.             if (c == ',')
  33.             {
  34.                 if (!string.IsNullOrEmpty(temp))
  35.                 {
  36.                     tokens.Add(temp);
  37.                     temp = "";
  38.                 }
  39.                 tokens.Add(",");
  40.                 continue;
  41.             }
  42.  
  43.             // Sprawdź czy to funkcja
  44.             if (char.IsLetter(c))
  45.             {
  46.                 temp += c;
  47.                 continue;
  48.             }
  49.  
  50.             // Obsługa operatorów
  51.             if (opMap.ContainsKey(c.ToString()) && c != '-')
  52.             {
  53.                 if (!string.IsNullOrEmpty(temp))
  54.                 {
  55.                     tokens.Add(temp);
  56.                     temp = "";
  57.                 }
  58.                 tokens.Add(c.ToString());
  59.             }
  60.             else if (c == '-')
  61.             {
  62.                 bool isUnary = (i == 0) ||
  63.                               (i > 0 && (opMap.ContainsKey(expression[i-1].ToString()) ||
  64.                                expression[i-1] == '(' ||
  65.                                expression[i-1] == ','));
  66.                
  67.                 if (!string.IsNullOrEmpty(temp) && !isUnary)
  68.                 {
  69.                     tokens.Add(temp);
  70.                     temp = "";
  71.                     tokens.Add(c.ToString());
  72.                 }
  73.                 else if (isUnary)
  74.                 {
  75.                     if (!string.IsNullOrEmpty(temp))
  76.                     {
  77.                         tokens.Add(temp);
  78.                         temp = "";
  79.                     }
  80.                     temp += c;
  81.                 }
  82.             }
  83.             else if (c == '(' || c == ')')
  84.             {
  85.                 if (!string.IsNullOrEmpty(temp))
  86.                 {
  87.                     tokens.Add(temp);
  88.                     temp = "";
  89.                 }
  90.                 tokens.Add(c.ToString());
  91.             }
  92.             else
  93.             {
  94.                 temp += c;
  95.             }
  96.         }
  97.         if (!string.IsNullOrEmpty(temp))
  98.         {
  99.             tokens.Add(temp);
  100.         }
  101.         return tokens;
  102.     }
  103.  
  104.     static List<string> InfixToPostfix(List<string> infix, Dictionary<string, int> opMap, List<string> functions)
  105.     {
  106.         List<string> postfix = new List<string>();
  107.         Stack<string> stack = new Stack<string>();
  108.         stack.Push("(");
  109.         infix.Add(")");
  110.  
  111.         foreach (string token in infix)
  112.         {
  113.             if (!opMap.ContainsKey(token) && !functions.Contains(token) &&
  114.                 token != "(" && token != ")" && token != ",")
  115.             {
  116.                 postfix.Add(token);
  117.             }
  118.             else if (token == "(")
  119.             {
  120.                 stack.Push("(");
  121.             }
  122.             else if (token == ")")
  123.             {
  124.                 while (stack.Peek() != "(")
  125.                 {
  126.                     postfix.Add(stack.Pop());
  127.                 }
  128.                 stack.Pop(); // Usuń "(" ze stosu
  129.                
  130.                 // Jeśli na stosie jest funkcja
  131.                 if (stack.Count > 0 && functions.Contains(stack.Peek()))
  132.                 {
  133.                     postfix.Add(stack.Pop());
  134.                 }
  135.             }
  136.             else if (token == ",")
  137.             {
  138.                 // Przetwarzaj argumenty funkcji
  139.                 while (stack.Peek() != "(")
  140.                 {
  141.                     postfix.Add(stack.Pop());
  142.                 }
  143.             }
  144.             else if (functions.Contains(token))
  145.             {
  146.                 stack.Push(token);
  147.             }
  148.             else
  149.             {
  150.                 while (stack.Count > 0 && opMap[token] <= opMap[stack.Peek()])
  151.                 {
  152.                     postfix.Add(stack.Pop());
  153.                 }
  154.                 stack.Push(token);
  155.             }
  156.         }
  157.         return postfix;
  158.     }
  159.  
  160.     static double CalculatePostfix(List<string> postfix, Dictionary<string, int> opMap, List<string> functions, Dictionary<string, double> constants)
  161.     {
  162.         Stack<double> stack = new Stack<double>();
  163.         int argCount = 1;
  164.  
  165.         foreach (string token in postfix)
  166.         {
  167.             if (opMap.ContainsKey(token))
  168.             {
  169.                 if (token == "u-")
  170.                 {
  171.                     double num = stack.Pop();
  172.                     stack.Push(-num);
  173.                 }
  174.                 else
  175.                 {
  176.                     double n1 = stack.Pop();
  177.                     double n2 = stack.Pop();
  178.                     switch (token[0])
  179.                     {
  180.                         case '+': stack.Push(n2 + n1); break;
  181.                         case '-': stack.Push(n2 - n1); break;
  182.                         case '*': stack.Push(n2 * n1); break;
  183.                         case '/': stack.Push(n2 / n1); break;
  184.                         case '^': stack.Push(Math.Pow(n2, n1)); break;
  185.                     }
  186.                 }
  187.                 argCount = 1;
  188.             }
  189.             else if (functions.Contains(token))
  190.             {
  191.                 if (token == "log")
  192.                 {
  193.                     if (argCount == 1)
  194.                     {
  195.                         double x = stack.Pop();
  196.                         stack.Push(Math.Log10(x));
  197.                     }
  198.                     else if (argCount == 2)
  199.                     {
  200.                         double x = stack.Pop();
  201.                         double a = stack.Pop();
  202.                         stack.Push((double)(Math.Log(x) / Math.Log(a)));
  203.                     }
  204.                 }
  205.                 else
  206.                 {
  207.                     double num = stack.Pop();
  208.                     switch (token)
  209.                     {
  210.                         case "exp": stack.Push(Math.Exp(num)); break;
  211.                         case "ln": stack.Push(Math.Log(num)); break;
  212.                         case "sqrt": stack.Push(Math.Sqrt(num)); break;
  213.                         case "sin": stack.Push(Math.Sin(num)); break;
  214.                         case "cos": stack.Push(Math.Cos(num)); break;
  215.                         case "tan": stack.Push(Math.Tan(num)); break;
  216.                         // Funkcje cyklometryczne (odwrotne do trygonometrycznych):
  217.                         case "arcsin": stack.Push(Math.Asin(num)); break;
  218.                         case "arccos": stack.Push(Math.Acos(num)); break;
  219.                         case "arctan": stack.Push(Math.Atan(num)); break;
  220.                         case "deg2rad": stack.Push(num * (Math.PI / 180.0)); break;
  221.                         case "rad2deg": stack.Push(num * (180.0 / Math.PI)); break;
  222.                     }
  223.                 }
  224.                 argCount = 1;
  225.             }
  226.             else if (constants.ContainsKey(token))
  227.             {
  228.                 stack.Push(constants[token]);
  229.             }
  230.             else if (token == ";")
  231.             {
  232.                 argCount++;
  233.             }
  234.             else
  235.             {
  236.                 stack.Push(double.Parse(token));
  237.             }
  238.         }
  239.         return stack.Pop();
  240.     }
  241.  
  242.     static void Main()
  243.     {
  244.            
  245.         CultureInfo.DefaultThreadCurrentCulture = Culture;
  246.         CultureInfo.DefaultThreadCurrentUICulture = Culture;
  247.        
  248.         Dictionary<string, int> opMap = new Dictionary<string, int>
  249.         {
  250.             {"^", 4},
  251.             {"u-", 3},
  252.             {"*", 2},
  253.             {"/", 2},
  254.             {"+", 1},
  255.             {"-", 1},
  256.             {"(", -1},
  257.             {")", -1},
  258.         };
  259.  
  260.         List<string> functions = new List<string> {
  261.             "exp", "ln", "log", "sqrt",
  262.             "sin", "cos", "tan",
  263.             "arcsin", "arccos", "arctan", // Funkcje cyklometryczne
  264.             "deg2rad", "rad2deg"
  265.         };
  266.  
  267.         Dictionary<string, double> constants = new Dictionary<string, double>
  268.         {
  269.             {"π", Math.PI},
  270.             {"e", Math.E},
  271.             {"pi",Math.PI}
  272.         };
  273.  
  274.         Console.WriteLine("Kalkulator naukowy");
  275.         Console.WriteLine("Dostępne stałe:");
  276.         Console.WriteLine("- π (pi) = 3.141592...");
  277.         Console.WriteLine("- e = 2.718281...");
  278.         Console.WriteLine("\nDostępne funkcje:");
  279.         Console.WriteLine("- Funkcje trygonometryczne: sin(x), cos(x), tan(x)");
  280.         Console.WriteLine("- Funkcje cyklometryczne (odwrotne do trygonometrycznych):");
  281.         Console.WriteLine("  arcsin(x), arccos(x), arctan(x)");
  282.         Console.WriteLine("- Konwersje: deg2rad(x), rad2deg(x)");
  283.         Console.WriteLine("- Pierwiastki i potęgi: sqrt(x), x^y");
  284.         Console.WriteLine("- Logarytmy: log(x), log(a,x), ln(x)");
  285.         Console.WriteLine("- Funkcja wykładnicza: exp(x)");
  286.         Console.WriteLine("\nPrzykłady:");
  287.         Console.WriteLine("  arcsin(0.5) → 0.523599 rad (30°)");
  288.         Console.WriteLine("  rad2deg(arccos(0.5)) → 60");
  289.         Console.WriteLine("  arctan(1) → 0.785398 rad (45°)");
  290.         Console.WriteLine("  sin(arcsin(0.8)) → 0.8");
  291.        
  292.         while (true)
  293.         {
  294.             Console.WriteLine("\nWprowadź wyrażenie (lub 'q' aby wyjść):");
  295.             string expression = Console.ReadLine();
  296.  
  297.             if (expression.ToLower() == "q") break;
  298.  
  299.             try
  300.             {
  301.                 List<string> tokens = Tokenize(expression, opMap, functions, constants);
  302.                 List<string> postfix = InfixToPostfix(tokens, opMap, functions);
  303.                 double result = CalculatePostfix(postfix, opMap, functions, constants);
  304.                
  305.                 Console.WriteLine(string.Format("Wynik: {0}", result));
  306.             }
  307.             catch (Exception ex)
  308.             {
  309.                 Console.WriteLine(string.Format("Błąd: {0}", ex.Message));
  310.             }
  311.         }
  312.     }
  313. }
  314.  
Advertisement
Add Comment
Please, Sign In to add comment