Skip to content

Commit 3806cf7

Browse files
committed
Added support for functions
1 parent efaa612 commit 3806cf7

File tree

7 files changed

+318
-21
lines changed

7 files changed

+318
-21
lines changed

Calculator.Tests/StandardizerTests.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace BLM16.Util.Calculator.Tests;
88
[TestClass]
99
public class StandardizerTests
1010
{
11-
private readonly Standardizer standardizer = new(Calculator.DefaultOperatorList, Calculator.DefaultConstantList);
11+
private readonly Standardizer standardizer = new(Calculator.DefaultOperatorList, Calculator.DefaultConstantList, Calculator.DefaultFunctionList);
1212

1313
/// <summary>
1414
/// Checks that whitespace is correctly removed from the equations
@@ -49,6 +49,22 @@ public void FixBrackets_ExceptionOnTooManyClosingBrackets(string equation)
4949

5050
#endregion
5151

52+
/// <summary>
53+
/// Checks that functions are correctly evaluated
54+
/// </summary>
55+
/// <param name="equation">The equation to standardize</param>
56+
/// <param name="expected">The expected output</param>
57+
[DataTestMethod]
58+
[DataRow("sqrt(64)", "(8)")]
59+
[DataRow("34log(100)", "34*(2)")]
60+
public void ComputeFunctions_ComputesFunctions(string equation, string expected)
61+
=> Assert.AreEqual(expected, standardizer.Standardize(equation));
62+
63+
/// <summary>
64+
/// Checks that constants are correctly replaced by their values
65+
/// </summary>
66+
/// <param name="equation">The equation to standardize</param>
67+
/// <param name="expected">The expected output</param>
5268
[DataTestMethod]
5369
[DataRow("pi", "(3.141592653589793)")]
5470
[DataRow("e", "(2.718281828459045)")]
@@ -59,7 +75,7 @@ public void ReplaceConstants_ReplacesConstants(string equation, string expected)
5975
/// <summary>
6076
/// Checks that multiplication signs are inserted correctly around brackets
6177
/// </summary>
62-
/// <param name="equation">The equatino to standardize</param>
78+
/// <param name="equation">The equation to standardize</param>
6379
/// <param name="expected">The expected output</param>
6480
[DataTestMethod]
6581
[DataRow("35(14+2)", "35*(14+2)")]

Calculator/Calculator.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,24 @@ public class Calculator
2929
/// The constants the calculator can use
3030
/// </summary>
3131
private readonly Constant[] constants;
32+
/// <summary>
33+
/// The functions the calculator can use
34+
/// </summary>
35+
private readonly Function[] functions;
3236

3337
/// <param name="operators">The list of operators the calculator recognizes. Defaults to <see cref="DefaultOperatorList"/> if no value is provided.</param>
34-
public Calculator(Operator[] operators = null, Constant[] constants = null)
38+
/// <param name="constants">The list of constants the calculator recognizes. Defaults to <see cref="DefaultConstantList"/> if no value is provided.</param>
39+
/// <param name="functions">The list of functions the calculator recognizes. Defaults to <see cref="DefaultFunctionList"/> if no value is provided.</param>
40+
public Calculator(Operator[] operators = null, Constant[] constants = null, Function[] functions = null)
3541
{
3642
// Use the default operators if no operators are provided
3743
this.operators = operators ?? DefaultOperatorList;
3844
// Use the default constants if no constants are provided
3945
this.constants = constants ?? DefaultConstantList;
46+
// Use the default functions if no functions are provided
47+
this.functions = functions ?? DefaultFunctionList;
4048

41-
standardizer = new Standardizer(this.operators, this.constants);
49+
standardizer = new Standardizer(this.operators, this.constants, this.functions);
4250
lexer = new Lexer(this.operators);
4351
parser = new Parser();
4452
}
@@ -80,4 +88,27 @@ public double Calculate(string equation)
8088
DefaultConstants.PI,
8189
DefaultConstants.E
8290
};
91+
92+
/// <summary>
93+
/// A list of the default functions used by the calculator
94+
/// </summary>
95+
public static Function[] DefaultFunctionList => new Function[]
96+
{
97+
DefaultFunctions.Sqrt,
98+
DefaultFunctions.Cbrt,
99+
DefaultFunctions.Cos,
100+
DefaultFunctions.Sin,
101+
DefaultFunctions.Tan,
102+
DefaultFunctions.Asin,
103+
DefaultFunctions.Acos,
104+
DefaultFunctions.Atan,
105+
DefaultFunctions.Floor,
106+
DefaultFunctions.Ceil,
107+
DefaultFunctions.Log,
108+
DefaultFunctions.Log2,
109+
DefaultFunctions.Log10,
110+
DefaultFunctions.Abs,
111+
DefaultFunctions.Deg,
112+
DefaultFunctions.Rad
113+
};
83114
}

Calculator/Calculator.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<Copyright>Copyright © 2021 Bradley Myers. All rights reserved.</Copyright>
99
<RepositoryUrl>https://github.com/BLM16/Tokenized-Calculator</RepositoryUrl>
1010
<RepositoryType>git</RepositoryType>
11-
<Version>3.0.0</Version>
11+
<Version>4.0.0</Version>
1212
<PackageLicenseFile>LICENSE</PackageLicenseFile>
1313
<PackageTags>calculator; math; solve</PackageTags>
1414
<PackageId>BLM16.Util.$(AssemblyName)</PackageId>
@@ -17,9 +17,14 @@
1717
<Description>This library parses and solves math equations from strings. Order of Operations Rules are followed.</Description>
1818
<NeutralLanguage>en-CA</NeutralLanguage>
1919
<RootNamespace>BLM16.Util.$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
20+
<PackageIcon>icon.png</PackageIcon>
2021
</PropertyGroup>
2122

2223
<ItemGroup>
24+
<None Include="..\icon.png">
25+
<Pack>True</Pack>
26+
<PackagePath>\</PackagePath>
27+
</None>
2328
<None Include="..\LICENSE">
2429
<Pack>True</Pack>
2530
<PackagePath></PackagePath>

Calculator/Models/Function.cs

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
using System;
2+
3+
namespace BLM16.Util.Calculator.Models;
4+
5+
/// <summary>
6+
/// A function used by the calculator
7+
/// </summary>
8+
public struct Function
9+
{
10+
/// <summary>
11+
/// The symbols that represent the function
12+
/// </summary>
13+
public string[] Symbols { get; private set; }
14+
/// <summary>
15+
/// The operation the function performs
16+
/// </summary>
17+
public Func<double, string> Operation { get; private set; }
18+
19+
public Function(Func<double, string> func, params string[] symbols)
20+
{
21+
Symbols = symbols;
22+
Operation = func;
23+
}
24+
}
25+
26+
/// <summary>
27+
/// Contains all the default functions built into the Calculator
28+
/// </summary>
29+
public static class DefaultFunctions
30+
{
31+
/// <summary>
32+
/// The absolute function
33+
/// </summary>
34+
public static Function Abs
35+
=> new((double val) => Math.Abs(val).ToString(), "abs");
36+
37+
/// <summary>
38+
/// The square root function
39+
/// </summary>
40+
public static Function Sqrt
41+
=> new((double val) => Math.Sqrt(val).ToString(), "sqrt", "root", "√");
42+
43+
/// <summary>
44+
/// The cubed root function
45+
/// </summary>
46+
public static Function Cbrt
47+
=> new((double val) => Math.Cbrt(val).ToString(), "cbrt", "sqrt3", "root3");
48+
49+
/// <summary>
50+
/// The sine function with a parameter in radians
51+
/// </summary>
52+
public static Function Sin
53+
=> new((double val) => Math.Sin(val).ToString(), "sin");
54+
55+
/// <summary>
56+
/// The cosine function with a parameter in radians
57+
/// </summary>
58+
public static Function Cos
59+
=> new((double val) => Math.Cos(val).ToString(), "cos");
60+
61+
/// <summary>
62+
/// The tangent function with a parameter in radians
63+
/// </summary>
64+
public static Function Tan
65+
=> new((double val) => Math.Tan(val).ToString(), "tan");
66+
67+
/// <summary>
68+
/// The inverse sine function
69+
/// </summary>
70+
public static Function Asin
71+
=> new((double val) => Math.Asin(val).ToString(), "asin", "arcsin", "sin^-1", "sin^(-1)");
72+
73+
/// <summary>
74+
/// The inverse cosine function
75+
/// </summary>
76+
public static Function Acos
77+
=> new((double val) => Math.Acos(val).ToString(), "acos", "arccos", "cos^-1", "cos^(-1)");
78+
79+
/// <summary>
80+
/// The inverse tangent function
81+
/// </summary>
82+
public static Function Atan
83+
=> new((double val) => Math.Atan(val).ToString(), "atan", "arctan", "tan^-1", "tan^(-1)");
84+
85+
/// <summary>
86+
/// The hyperbolic sine function
87+
/// </summary>
88+
public static Function Sinh
89+
=> new((double val) => Math.Sinh(val).ToString(), "sinh");
90+
91+
/// <summary>
92+
/// The hyperbolic cosine function
93+
/// </summary>
94+
public static Function Cosh
95+
=> new((double val) => Math.Cosh(val).ToString(), "cosh");
96+
97+
/// <summary>
98+
/// The hyperbolic tangent function
99+
/// </summary>
100+
public static Function Tanh
101+
=> new((double val) => Math.Tanh(val).ToString(), "tanh");
102+
103+
/// <summary>
104+
/// The inverse hyperbolic sine function
105+
/// </summary>
106+
public static Function Asinh
107+
=> new((double val) => Math.Asinh(val).ToString(), "asinh", "arcsinh", "sinh^-1", "sinh^(-1)");
108+
109+
/// <summary>
110+
/// The inverse hyperbolic cosine function
111+
/// </summary>
112+
public static Function Acosh
113+
=> new((double val) => Math.Acosh(val).ToString(), "acosh", "arccosh", "cosh^-1", "cosh^(-1)");
114+
115+
/// <summary>
116+
/// The inverse hyperbolic tangent function
117+
/// </summary>
118+
public static Function Atanh
119+
=> new((double val) => Math.Atanh(val).ToString(), "atanh", "arctanh", "tanh^-1", "tanh^(-1)");
120+
121+
/// <summary>
122+
/// The ceiling function
123+
/// </summary>
124+
public static Function Ceil
125+
=> new((double val) => Math.Ceiling(val).ToString(), "ceil");
126+
127+
/// <summary>
128+
/// The floor function
129+
/// </summary>
130+
public static Function Floor
131+
=> new((double val) => Math.Floor(val).ToString(), "floor");
132+
133+
/// <summary>
134+
/// The sign function
135+
/// </summary>
136+
public static Function Sign
137+
=> new((double val) => Math.Sign(val).ToString(), "sign", "sgn");
138+
139+
/// <summary>
140+
/// The logarithm function of base e
141+
/// </summary>
142+
public static Function Log
143+
=> new((double val) => Math.Log(val).ToString(), "loge", "log_e", "ln");
144+
145+
/// <summary>
146+
/// The logarithm function of base 2
147+
/// </summary>
148+
public static Function Log2
149+
=> new((double val) => Math.Log2(val).ToString(), "log2", "log_2");
150+
151+
/// <summary>
152+
/// The logarithm function of base 10
153+
/// </summary>
154+
public static Function Log10
155+
=> new((double val) => Math.Log10(val).ToString(), "log10", "log_10", "log");
156+
157+
/// <summary>
158+
/// The degree function converts radians to degrees
159+
/// </summary>
160+
public static Function Deg
161+
=> new((double val) => (val * 180 / Math.PI).ToString(), "deg");
162+
163+
/// <summary>
164+
/// The radian function converts degrees to radians
165+
/// </summary>
166+
public static Function Rad
167+
=> new((double val) => (val * Math.PI / 180).ToString(), "rad");
168+
}

0 commit comments

Comments
 (0)