Skip to content

jr20xx/JCalc

Repository files navigation

Banner

Status

Testing License Repository Size JitPack

Table of Contents

Description of the project

This repo holds the code of a Java library named JCalc made for parsing Math expressions as strings and quickly solve them. In order to make that possible, this library makes use of a custom implementation of the Shunting Yard algorithm that allows it to quickly parse and solve Math expressions written in the notation commonly used to write Math expressions; also known as infix notation.

You can use this library to solve Math expressions like, for example:

  • ((25*3-9)/(4+2)+5^3)-(48/8)*(7+2)+14 (which is equals to 96)
  • 3 + 4 * 2 / (1 - 5)^2^3 (which is equals to 3.000122070313)
  • 1000 / (2^5) + (3!)^4 - 500 * (2 + 3) (which is equals to -1172.75)
  • (8^2 + 15 * 4 - 7) / (3 + 5)*(12 - 9) + 6^2 - (18 /3) + 11 (which is equals to 84.875)
  • (2^10)! / (2^(5!)) (which is equals to 4.076447993302E2603)
  • ((100 + 200) * (300 - 150)) / (2^(3!)) + (7!)^25 (which is equals to 3.637168415833E92)
  • (-2^3) * (-(3! + 4) / 2) + 5 (which is equals to 45)
  • 2 + -3! * (-4^2) / (5 - 3) (which is equals to 50)

All the expressions previously shown are just a few examples. The results were obtained with JCalc and checked using an online calculator app provided by Desmos in this website.

Getting the library

Building the library locally

To build the library locally, the first thing you must do is to make sure that you have a valid installation of the Java Development Kit (JDK). That can be easily checked by executing the following command in a terminal:

java --version

Note

The minimum Java version required to build this library is Java 8.

If the execution of that command generates any output instead of an error message, then your installation of the JDK should be correct. After effectively checking the JDK installation, you must create a local copy of this repo in your device and, in order to do that, launch a terminal and execute the following command:

git clone https://github.com/jr20xx/JCalc

Once the execution of that command is finished, a new directory containing a copy of the files of this project will be created. You can open that folder with a Java IDE with Gradle support like IntelliJ IDEA, Android Studio or VSCode (with the Extension Pack for Java installed) and then build the library making use of their integrated tools. If you need help doing that, you can check this website to get references of how to do that in your preferred IDE.

If you decide to build the library without using any IDE, then open the newly created directory containing the files from this repo and start a terminal session from there. Once you've opened a terminal, run any of the following commands:

From Linux terminal:

./gradlew build

From Windows command line:

gradlew.bat build

Once the execution of that command is done, open the jcalc directory, then open the builds directory and, once you are watching its content, you'll see a folder named libs. In that last folder you'll find compiled files of the library, the Javadocs and the source code compressed as independent JAR files that you can use as you wish. Here's a representation of the portion of the directories tree mentioned before, in plaintext format:

JCalc (parent folder)
├── jcalc
│   ├── build
│   │   ├── libs
│   │   │   ├── jcalc-X.Y.Z.jar
│   │   │   ├── jcalc-X.Y.Z-javadoc.jar
│   │   │   └── jcalc-X.Y.Z-sources.jar

Note

Please notice that "X", "Y" and "Z" are used as placeholders in the names of the JAR files. They take the place of the version numbers of the library and are not part of the actual names of the compiled files.

Getting the library from JitPack

To ease the process of getting a compiled version of the library that you can use directly in your projects, you can use JitPack. In order to do that, follow the official guide provided here by JitPack.

Usage

Supported operators

JCalc comes with support for numbers written using a variant of the Scientific notation named E notation and it also supports the usage of the Math constants "e" and "π" directly in the input expressions. Besides that, you can also make use of parentheses ("(" and ")").

The following tables summarize the rest of the symbols or tokens currently supported as operators. You can use any of those operators when writing the Math expressions and any other operator or value not included in those tables is currently not supported. If you use any symbol not included in any of the given tables, an exception will be thrown.

Basic operators
Addition + Subtraction -
Multiplication * or × Division / or ÷
Exponentiation ^ Factorial !
Advanced operators
Sine sin Cosine cos
Tangent tan Arcsine asin or arcsin
Arccosine acos or arccos Arctangent atan or arctan
Cosecant csc Secant sec
Cotangent cot Natural logarithm ln
Base 2 logarithm log2 Base 10 logarithm log
Square root or sqrt Cube root cbrt

Tip

It is strongly recommended to use parentheses in Math expressions to avoid parsing inaccuracies or ambiguity. That's because, for example, log28 will be parsed as log2(8) if you don't use parentheses before the number "2" in "28"; so, if what you actually want is to get the base 10 logarithm, you have to use log(28) instead.

Warning

  • The support for the advanced operators is still under development.
  • The library is case sensitive and that means that, for example, "E" and "e" are treated differently based on their casing.

Basic usage

In order to solve Math expressions, you just have to call the JCalc.solveMathExpression(...) method, passing a String to it containing the Math expression that you want to get solved. When called, that method will return another String with the result of solving the given Math expression and any whitespace in the Math expression will be ignored. If the given expression is either empty, null or contains only whitespaces, null will be returned as result. To help you get a better idea of what was previously described, here's a code example:

String expression = "3 + 4 * 2 / (1 - 5)^2^3";
String result = JCalc.solveMathExpression(expression);
System.out.print(result); // Prints "3.000122070313"

Advanced usage

One of the main ideas behind the creation of JCalc is to allow a certain level of customization in the way it works; and that's precisely why it has an alternative JCalc.solveMathExpression(...) method that, in addition to taking the Math expression as first parameter, also receives an instance of the ConfigurationBuilder class as second parameter. This alternative method works nearly in the same way as it was described in the basic usage section, returning the same type of data and only taking an additional parameter of the ConfigurationBuilder type to customize certain settings of the library.

The ConfigurationBuilder class, introduced in the third version of the library, includes methods to customize how the library behaves. It has a method to control the precision of the final result obtained when the Math expression is completely solved and, in addition to that, there's also a method that allows you to toggle the functionality to make an attempt to balance the parentheses in a given Math expression. Finally, it also contains another method that lets you control whether to use radians or degrees when dealing with trigonometric functions. Here's an example of how to create a new instance of the ConfigurationBuilder class and how to set up all the parameters previously mentioned one by one to later solve a Math expression:

ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.setPrecision(10);
configurationBuilder.setBalanceParentheses(true);
configurationBuilder.setUseRadians(false);
String expression = "3 + 4 * 2 / (1 - 5)^2^3";
String result = JCalc.solveMathExpression(expression, configurationBuilder);
System.out.print(result); // Prints "3.0001220703"

Alternatively, you can set up all those parameters all at once as it follows:

ConfigurationBuilder configurationBuilder = new ConfigurationBuilder().setPrecision(10).setBalanceParentheses(true).setUseRadians(false);
String expression = "3 + 4 * 2 / (1 - 5)^2^3";
String result = JCalc.solveMathExpression(expression, configurationBuilder);
System.out.print(result); // Prints "3.0001220703"

If you forget to customize any parameter or just create a new instance of ConfigurationBuilder without setting up any parameter, the default values will be used instead. The default value for precision is 12 and the minimum accepted value for that setting is 3; so if you try to set it to a lower number, it will default to 3. Besides all that, the library defaults to radians when dealing with trigonometric functions and, by default, it disables the process to balance the parentheses in a Math expression.

Warning

If you pass null instead of a valid instance of the ConfigurationBuilder, you'll get an IllegalArgumentException.

Exceptions handling

This library contains a small set of custom exceptions that should be controlled to guarantee that the execution of the program doesn't get interrupted or glitched. Here's a Java snippet showing all of them with added comments explaining when they are expected to happen:

try {
    String expression = "2 * 3 + 5 * 2^3)";
    String result = JCalc.solveMathExpression(expression);
}
catch (UnbalancedParenthesesException exception) {
    // This exception occurs when the parentheses were not placed correctly and `false` is provided as second parameter
}
catch (NotNumericResultException exception) {
    // This exception occurs when a not numeric (NaN) value is obtained
}
catch (InfiniteResultException exception) {
    // This exception occurs when an Infinite result is obtained
}
catch (SyntaxErrorException exception) {
    // This exception occurs when an error is detected in the writing of the Math expression
}
catch (NumericalDomainErrorException exception) {
    // This exception occurs when trying to obtain the factorial of a number when it's negative or not an integer
}
catch (Exception exception) {
    // This is recommended in case that an unexpected exception arises
}

Related project (W.I.P.)

Testing

In order to provide a more reliable mechanism that also ensures that JCalc works as expected, JUnit tests were implemented. Thanks to this GitHub workflow, they are run on each commit or pull request to also follow some Continuous Integration principles.

So far there are just a few tests cases written and they still don't cover all the functionalities of the library. Feel free to write your own when you clone or fork this repo and then suggest some of your own test cases (the more complicated, the best).

Test cases are located under ./jcalc/src/test/resources as CSV files you can edit as you please without embedding them in the testing class directly. When you suggest new tests, please follow that principle: use standalone CSV files and later add references to them in the testing class instead of embedding test cases in the code of the testing class.

About the docs

The code included in this library includes Javadocs comments nearly everywhere and the rest of the code will be documented in the same way soon. Thanks to JitPack, you can read the online version of the Javadocs by visiting this website.

Contribution

We value a lot any kind of contribution and we encourage you to submit pull requests and provide tutorials or other relevant content that might help to improve this library or extend its functionalities.

You can also contribute to this repo by adding a star to it and/or sharing the link if you find it helpful in some way. Any form of help will be highly appreciated.