diff --git a/.idea/.idea.calculator/.idea/git_toolbox_prj.xml b/.idea/.idea.calculator/.idea/git_toolbox_prj.xml
new file mode 100644
index 0000000..02b915b
--- /dev/null
+++ b/.idea/.idea.calculator/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Commands/CalculateCommand.cs b/Commands/CalculateCommand.cs
deleted file mode 100644
index 782282f..0000000
--- a/Commands/CalculateCommand.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using calculator.Common;
-using calculator.Model;
-using calculator.Services;
-
-namespace calculator.Commands;
-
-public class CalculateCommand : ICommand
-{
- private readonly ICaculator _caculator;
- private readonly CaculatorData _data;
- private readonly double? _b;
- private readonly Operation _operation;
- private double? _previousValue;
-
- public CalculateCommand(ICaculator caculator, CaculatorData data)
- {
- _caculator = caculator;
- _data = data;
- _operation = data.Operation.Value;
-
- if (double.TryParse(data.Input, out var b))
- _b = b;
- }
-
- public void Execute()
- {
- if (_data.Value is null)
- return;
- _previousValue = _data.Value;
- _data.Value = _caculator.Calculate(_operation, _data.Value.Value, _b);
- _data.Input = null;
- }
-
- public void Undo()
- {
- _data.Value = _previousValue;
- }
-}
\ No newline at end of file
diff --git a/Common/CalculatorExtensions.cs b/Common/CalculatorExtensions.cs
new file mode 100644
index 0000000..d3d9765
--- /dev/null
+++ b/Common/CalculatorExtensions.cs
@@ -0,0 +1,54 @@
+namespace calculator.Common;
+
+public static class CalculatorExtensions
+{
+ public static int Precedence(this Operation op)
+ {
+ switch (op)
+ {
+ case Operation.Add:
+ case Operation.Sub:
+ return 1;
+ case Operation.Mul:
+ case Operation.Div:
+ case Operation.Factorial:
+ return 2;
+ case Operation.PowY:
+ case Operation.SqrtY:
+ return 3;
+ case Operation.Cube:
+ case Operation.Pow:
+ case Operation.Sqrt:
+ case Operation.CubeRoot:
+ case Operation.Square:
+ case Operation.Log:
+ case Operation.Ln:
+ case Operation.Inv:
+ case Operation.OneDiv:
+ case Operation.Mod:
+ case Operation.Neg:
+ case Operation.Percent:
+ case Operation.Sinh:
+ case Operation.Sin:
+ case Operation.Cosh:
+ case Operation.Cos:
+ case Operation.Tanh:
+ case Operation.Tan:
+ return 4;
+ default:
+ case Operation.OpenBracket:
+ case Operation.CloseBracket:
+ return 0;
+ }
+ }
+
+ public static bool IsBigger(this Operation a, Operation b)
+ {
+ return Precedence(a) > Precedence(b);
+ }
+
+ public static bool IsLowerOrEqual(this Operation a, Operation b)
+ {
+ return Precedence(a) <= Precedence(b);
+ }
+}
\ No newline at end of file
diff --git a/Common/Operation.cs b/Common/Operation.cs
index b969da4..37a490e 100644
--- a/Common/Operation.cs
+++ b/Common/Operation.cs
@@ -18,7 +18,6 @@ public enum Operation
Ln,
Exp,
Inv,
- Pi,
OneDiv,
Mod,
Neg,
@@ -28,5 +27,16 @@ public enum Operation
Cosh,
Cos,
Tanh,
- Tan
+ Tan,
+ OpenBracket,
+ CloseBracket,
+ Int,
+ Dms,
+ FE,
+ PowX
+}
+public enum Constants
+{
+ Pi,
+ Exp
}
\ No newline at end of file
diff --git a/Controller/CaculatorController.cs b/Controller/CaculatorController.cs
index 612b414..ed35880 100644
--- a/Controller/CaculatorController.cs
+++ b/Controller/CaculatorController.cs
@@ -1,8 +1,8 @@
-using calculator.Commands;
-using calculator.Common;
+using calculator.Common;
using calculator.Model;
using calculator.Services;
using calculator.View;
+using System.Runtime.InteropServices;
namespace calculator.Controller;
@@ -12,7 +12,6 @@ public class CaculatorController
private readonly IInputService _inputService;
private readonly ICaculatorView _view;
private readonly CaculatorData _data;
- private ICommand? _currentCommand;
public CaculatorController(ICaculator caculator, IInputService inputService, ICaculatorView view,
CaculatorData data)
@@ -27,14 +26,24 @@ public class CaculatorController
_view.ClearPressed += OnClearPressed;
_view.CalculatePressed += OnCalculatePressed;
_view.SingleOperatorPressed += OnSingleOperationPressed;
+ _view.Constants += OnConstantsPressed;
OnClearPressed(true);
}
private void OnSingleOperationPressed(Operation operation)
{
- OnOperatorPressed(operation);
- _currentCommand = new CalculateCommand(_caculator, _data);
- OnCalculatePressed();
+ if (double.TryParse(_data.Input, out var value) == false)
+ {
+ if (_data.Values.Count > 0)
+ {
+ value = _data.Values.Pop()!.Value;
+ }
+ else { return; }
+ }
+
+ _data.Values.Push(_caculator.Calculate(operation, value));
+ UpdateView(_data.Values.Peek()!.Value);
+ _data.Input = null;
}
private void OnClearPressed(bool full)
@@ -42,60 +51,104 @@ public class CaculatorController
Clear(full: full);
}
+ private void Calculate(bool fullAnswer = true)
+ {
+ if (_data.Operations.Count == 0)
+ return;
+
+ if (_data.Values.Count == 0)
+ return;
+
+ if (TryGetValueFromInput() == false)
+ return;
+
+ PerformCalculation(fullAnswer);
+
+ UpdateView(_data.Values.Peek()!.Value);
+ }
+
private void OnCalculatePressed()
{
- if (_data.Operation is null)
- return;
+ Calculate();
+ }
- if (_data.Value is null)
- return;
-
- if (_data is not { Caculated: true, Input: null } || _currentCommand == null)
+ private void PerformCalculation(bool fullAnswer = true)
+ {
+ while (true)
{
- _currentCommand = new CalculateCommand(_caculator, _data);
+ while (_data.Operations.Count > 0 && _data.Operations.Peek() != Operation.OpenBracket)
+ {
+ var b = _data.Values.Pop();
+ var a = _data.Values.Pop();
+ _data.Values.Push(_caculator.Calculate(_data.Operations.Pop(), a!.Value, b!.Value));
+ }
+
+ if (_data.Operations.Count > 0 && _data.Operations.Peek() == Operation.OpenBracket && fullAnswer)
+ {
+ _data.Operations.Pop();
+ }
+
+ if (_data.Operations.Count > 0 && fullAnswer)
+ {
+ continue;
+ }
+
+ break;
}
-
- _currentCommand?.Execute();
- _data.Caculated = true;
- UpdateView(_data.Value.Value);
}
private void Clear(string value = "0", bool full = true)
{
if (full)
{
- _data.Value = null;
- _data.Operation = null;
+ _data.Values.Clear();
+ _data.Operations.Clear();
}
-
- _data.Caculated = false;
+
_data.Input = null;
_view.UpdateView(value);
}
private void OnOperatorPressed(Operation operation)
{
- if (_data.Input == null && _data.Value == null)
- return;
-
- if (_data is { Caculated: false, Input: not null, Value: not null })
+ if (_data.Operations.Count > 0)
{
- OnCalculatePressed();
+ if (operation == Operation.CloseBracket)
+ {
+ Calculate(false);
+ return;
+ }
+
+ if (operation != Operation.OpenBracket && operation.IsLowerOrEqual(_data.Operations.Peek()))
+ {
+ Calculate(false);
+ }
}
- _data.Operation = operation;
+ _data.Operations.Push(operation);
- if (_data.Input != null)
+ TryGetValueFromInput();
+ }
+
+ private bool TryGetValueFromInput()
+ {
+ if (_data.Input is not null)
{
- _data.Value = double.Parse(_data.Input);
+ if (double.TryParse(_data.Input, out var value) == false)
+ {
+ return false;
+ }
+
+ _data.Values.Push(value);
}
_data.Input = null;
+ return true;
}
private void OnOperandPressed(char obj)
{
- if (_data.Caculated)
+ if (_data.Operations.Count == 0 && _data.Input == null)
{
Clear(full: true);
}
@@ -113,4 +166,26 @@ public class CaculatorController
{
_view.UpdateView(input);
}
-}
\ No newline at end of file
+
+ private void OnConstantsPressed(Constants constants)
+ {
+ if (_data.Operations.Count == 0 && _data.Input == null)
+ {
+ Clear(full: true);
+ }
+
+ double output = 0;
+ switch (constants)
+ {
+ case Constants.Pi:
+ output = Math.PI;
+ break;
+ case Constants.Exp:
+ output = Math.E;
+ break;
+ }
+ _data.Input = output.ToString("0.#####");
+ UpdateView(output);
+ }
+}
+
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
index 53bd2c3..5af0b11 100644
--- a/Form1.Designer.cs
+++ b/Form1.Designer.cs
@@ -29,7 +29,7 @@
private void InitializeComponent()
{
panel1 = new Panel();
- button49 = new Button();
+ PowX = new Button();
Log_button = new Button();
Mod_button = new Button();
Exp_button = new Button();
@@ -97,7 +97,7 @@
// panel1
//
panel1.BackColor = Color.MediumSlateBlue;
- panel1.Controls.Add(button49);
+ panel1.Controls.Add(PowX);
panel1.Controls.Add(Log_button);
panel1.Controls.Add(Mod_button);
panel1.Controls.Add(Exp_button);
@@ -157,16 +157,17 @@
panel1.Size = new Size(573, 338);
panel1.TabIndex = 0;
//
- // button49
+ // PowX
//
- button49.FlatStyle = FlatStyle.Flat;
- button49.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
- button49.Location = new Point(232, 296);
- button49.Name = "button49";
- button49.Size = new Size(51, 37);
- button49.TabIndex = 55;
- button49.Text = "10ᵜ";
- button49.UseVisualStyleBackColor = true;
+ PowX.FlatStyle = FlatStyle.Flat;
+ PowX.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ PowX.Location = new Point(232, 296);
+ PowX.Name = "PowX";
+ PowX.Size = new Size(51, 37);
+ PowX.TabIndex = 55;
+ PowX.Text = "10ᵜ";
+ PowX.UseVisualStyleBackColor = true;
+ PowX.Click += OnPowXButtonClick;
//
// Log_button
//
@@ -206,8 +207,11 @@
//
// button53
//
+ button53.Cursor = Cursors.No;
+ button53.Enabled = false;
button53.FlatStyle = FlatStyle.Flat;
button53.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ button53.ForeColor = Color.Tomato;
button53.Location = new Point(4, 296);
button53.Name = "button53";
button53.Size = new Size(51, 37);
@@ -325,8 +329,12 @@
//
// dms_button
//
+ dms_button.BackgroundImageLayout = ImageLayout.None;
+ dms_button.Cursor = Cursors.No;
+ dms_button.Enabled = false;
dms_button.FlatStyle = FlatStyle.Flat;
dms_button.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ dms_button.ForeColor = Color.Tomato;
dms_button.Location = new Point(4, 210);
dms_button.Name = "dms_button";
dms_button.Size = new Size(51, 37);
@@ -392,6 +400,7 @@
Int_button.TabIndex = 36;
Int_button.Text = "Int";
Int_button.UseVisualStyleBackColor = true;
+ Int_button.Click += OnIntButtonClick;
//
// button23
//
@@ -403,6 +412,7 @@
button23.TabIndex = 35;
button23.Text = ")";
button23.UseVisualStyleBackColor = true;
+ button23.Click += OnCloseBracketButtonClick;
//
// button30
//
@@ -414,6 +424,7 @@
button30.TabIndex = 34;
button30.Text = "(";
button30.UseVisualStyleBackColor = true;
+ button30.Click += OnOpenBracketButtonClick;
//
// Ln_button
//
@@ -729,8 +740,11 @@
//
// button5
//
+ button5.Cursor = Cursors.No;
+ button5.Enabled = false;
button5.FlatStyle = FlatStyle.Flat;
button5.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ button5.ForeColor = Color.Tomato;
button5.Location = new Point(517, 81);
button5.Name = "button5";
button5.Size = new Size(51, 37);
@@ -740,8 +754,11 @@
//
// button4
//
+ button4.Cursor = Cursors.No;
+ button4.Enabled = false;
button4.FlatStyle = FlatStyle.Flat;
button4.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ button4.ForeColor = Color.Tomato;
button4.Location = new Point(460, 81);
button4.Name = "button4";
button4.Size = new Size(51, 37);
@@ -751,8 +768,11 @@
//
// button3
//
+ button3.Cursor = Cursors.No;
+ button3.Enabled = false;
button3.FlatStyle = FlatStyle.Flat;
button3.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ button3.ForeColor = Color.Tomato;
button3.Location = new Point(403, 81);
button3.Name = "button3";
button3.Size = new Size(51, 37);
@@ -762,8 +782,11 @@
//
// button2
//
+ button2.Cursor = Cursors.No;
+ button2.Enabled = false;
button2.FlatStyle = FlatStyle.Flat;
button2.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ button2.ForeColor = Color.Tomato;
button2.Location = new Point(346, 81);
button2.Name = "button2";
button2.Size = new Size(51, 37);
@@ -773,8 +796,11 @@
//
// button1
//
+ button1.Cursor = Cursors.No;
+ button1.Enabled = false;
button1.FlatStyle = FlatStyle.Flat;
button1.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point);
+ button1.ForeColor = Color.Tomato;
button1.Location = new Point(289, 81);
button1.Name = "button1";
button1.Size = new Size(51, 37);
@@ -796,8 +822,11 @@
// radioButton3
//
radioButton3.AutoSize = true;
+ radioButton3.BackgroundImageLayout = ImageLayout.None;
+ radioButton3.Cursor = Cursors.No;
+ radioButton3.Enabled = false;
radioButton3.Font = new Font("Microsoft Sans Serif", 11.25F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
- radioButton3.ForeColor = Color.FromArgb(255, 192, 255);
+ radioButton3.ForeColor = Color.Tomato;
radioButton3.Location = new Point(197, 13);
radioButton3.Name = "radioButton3";
radioButton3.Size = new Size(76, 22);
@@ -809,8 +838,11 @@
// radioButton2
//
radioButton2.AutoSize = true;
+ radioButton2.BackgroundImageLayout = ImageLayout.None;
+ radioButton2.Cursor = Cursors.No;
+ radioButton2.Enabled = false;
radioButton2.Font = new Font("Microsoft Sans Serif", 11.25F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
- radioButton2.ForeColor = Color.FromArgb(255, 192, 255);
+ radioButton2.ForeColor = Color.Tomato;
radioButton2.Location = new Point(98, 13);
radioButton2.Name = "radioButton2";
radioButton2.Size = new Size(95, 22);
@@ -822,8 +854,11 @@
// radioButton1
//
radioButton1.AutoSize = true;
+ radioButton1.BackgroundImageLayout = ImageLayout.None;
+ radioButton1.Cursor = Cursors.No;
+ radioButton1.Enabled = false;
radioButton1.Font = new Font("Microsoft Sans Serif", 11.25F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);
- radioButton1.ForeColor = Color.FromArgb(255, 192, 255);
+ radioButton1.ForeColor = Color.Tomato;
radioButton1.Location = new Point(6, 13);
radioButton1.Name = "radioButton1";
radioButton1.Size = new Size(93, 22);
@@ -848,6 +883,7 @@
// linkLabel1
//
linkLabel1.AutoSize = true;
+ linkLabel1.Enabled = false;
linkLabel1.LinkColor = Color.FromArgb(255, 192, 255);
linkLabel1.Location = new Point(16, 6);
linkLabel1.Name = "linkLabel1";
@@ -859,6 +895,7 @@
// linkLabel2
//
linkLabel2.AutoSize = true;
+ linkLabel2.Enabled = false;
linkLabel2.LinkColor = Color.FromArgb(255, 192, 255);
linkLabel2.Location = new Point(49, 6);
linkLabel2.Name = "linkLabel2";
@@ -870,6 +907,7 @@
// linkLabel3
//
linkLabel3.AutoSize = true;
+ linkLabel3.Enabled = false;
linkLabel3.LinkColor = Color.FromArgb(255, 192, 255);
linkLabel3.Location = new Point(102, 6);
linkLabel3.Name = "linkLabel3";
@@ -914,7 +952,7 @@
private LinkLabel linkLabel1;
private LinkLabel linkLabel2;
private LinkLabel linkLabel3;
- private Button button49;
+ private Button PowX;
private Button Log_button;
private Button Mod_button;
private Button Exp_button;
diff --git a/Form1.cs b/Form1.cs
index 074e7e4..a718b22 100644
--- a/Form1.cs
+++ b/Form1.cs
@@ -15,6 +15,7 @@ namespace calculator
public event Action? SingleOperatorPressed;
public event Action? ClearPressed;
public event Action? CalculatePressed;
+ public event Action? Constants;
public void UpdateView(string input)
{
@@ -83,7 +84,7 @@ namespace calculator
private void OnDotButtonClick(object sender, EventArgs e)
{
- OperandPressed?.Invoke('.');
+ OperandPressed?.Invoke(',');
}
private void OnNegativeButtonClick(object sender, EventArgs e)
@@ -198,7 +199,7 @@ namespace calculator
private void OnLogButtonClick(object sender, EventArgs e)
{
- SingleOperatorPressed?.Invoke(Operation.Log);
+ OperatorPressed?.Invoke(Operation.Log);
}
private void OnInvButtonClick(object sender, EventArgs e)
@@ -213,13 +214,32 @@ namespace calculator
private void OnExpButtonClick(object sender, EventArgs e)
{
- SingleOperatorPressed?.Invoke(Operation.Exp);
+ Constants?.Invoke(Common.Constants.Exp);
}
private void OnPiButtonClick(object sender, EventArgs e)
{
- SingleOperatorPressed?.Invoke(Operation.Pi);
+ Constants?.Invoke(Common.Constants.Pi);
}
+ private void OnOpenBracketButtonClick(object? sender, EventArgs e)
+ {
+ OperatorPressed?.Invoke(Operation.OpenBracket);
+ }
+
+ private void OnCloseBracketButtonClick(object? sender, EventArgs e)
+ {
+ OperatorPressed?.Invoke(Operation.CloseBracket);
+ }
+
+ private void OnIntButtonClick(object sender, EventArgs e)
+ {
+ SingleOperatorPressed?.Invoke(Operation.Int);
+ }
+
+ private void OnPowXButtonClick(object sender, EventArgs e)
+ {
+ SingleOperatorPressed?.Invoke(Operation.PowX);
+ }
}
}
\ No newline at end of file
diff --git a/Form1.resx b/Form1.resx
index 2a5f517..5254a5f 100644
--- a/Form1.resx
+++ b/Form1.resx
@@ -120,78 +120,18 @@
True
-
- True
-
-
- True
-
-
- True
-
-
+
True
True
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
-
- True
-
True
True
-
- True
-
-
- True
-
True
diff --git a/Model/CaculatorData.cs b/Model/CaculatorData.cs
index ddcd271..87e12c5 100644
--- a/Model/CaculatorData.cs
+++ b/Model/CaculatorData.cs
@@ -5,7 +5,6 @@ namespace calculator.Model;
public class CaculatorData
{
public string? Input { get; set; }
- public double? Value { get; set; }
- public Operation? Operation { get; set; }
- public bool Caculated { get; set; }
+ public Stack Values { get; set; } = new();
+ public Stack Operations { get; set; } = new();
}
\ No newline at end of file
diff --git a/Services/Caculyator.cs b/Services/Caculyator.cs
index ea95d7f..b1c896d 100644
--- a/Services/Caculyator.cs
+++ b/Services/Caculyator.cs
@@ -31,6 +31,8 @@ namespace calculator.Services
return Math.Pow(a, b);
case Operation.Mod:
return a % b;
+ case Operation.Log:
+ return Math.Log(a, b);
default:
throw new ArgumentException($"Invalid operator: {token}");
}
@@ -75,16 +77,14 @@ namespace calculator.Services
return Math.Pow(a, 3);
case Operation.CubeRoot:
return Math.Pow(a, 1 / 3);
- case Operation.Log:
- return Math.Log10(a);
case Operation.Ln:
return Math.Log(a);
- case Operation.Exp:
- return Math.Exp(a);
case Operation.Inv:
return 1 / a;
- case Operation.Pi:
- return Math.PI;
+ case Operation.Int:
+ return Math.Round(a);
+ case Operation.PowX:
+ return Math.Pow(10, a);
default:
throw new ArgumentException($"Invalid operator: {token}");
}
diff --git a/View/ICaculatorView.cs b/View/ICaculatorView.cs
index 6044b09..7d9ea53 100644
--- a/View/ICaculatorView.cs
+++ b/View/ICaculatorView.cs
@@ -9,5 +9,6 @@ public interface ICaculatorView
public event Action ClearPressed;
public event Action CalculatePressed;
public event Action SingleOperatorPressed;
+ public event Action Constants;
public void UpdateView(string input);
}
\ No newline at end of file