**Get started with Spring 5 and Spring Boot 2, through the ***Learn Spring* course:

*Learn Spring*course:

**>> CHECK OUT THE COURSE**

Last modified: August 20, 2019

We're frequently in need of using mathematical tools, and sometimes *java.lang.Math *is simply not enough. Fortunately, Apache Commons has the goal of filling in the leaks of the standard library, with Apache Commons Math.

Apache Commons Math is the biggest open-source library of mathematical functions and utilities for Java. Given that this article is just an introduction, we will just give an overview of the library and present the most compelling use cases.

Apache Commons Math consists of mathematical functions (*erf* for instance), structures representing mathematical concepts (like complex numbers, polynomials, vectors, etc.), and algorithms that we can apply to these structures (root finding, optimization, curve fitting, computation of intersections of geometrical figures, etc.).

If you're using Maven, simply add this dependency:

```
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
```

Apache Commons Math is divided into several packages:

statistics and statistical tests**org.apache.commons.math3.stat –**probability distributions**org.apache.commons.math3.distribution –**random numbers, strings and data generation**org.apache.commons.math3.random –**root finding, integration, interpolation, polynomials, etc.**org.apache.commons.math3.analysis –**matrices, solving linear systems**org.apache.commons.math3.linear –**geometry (Euclidean spaces and binary space partitioning)**org.apache.commons.math3.geometry –**transform methods (fast Fourier)**org.apache.commons.math3.transform –**ordinary differential equations integration**org.apache.commons.math3.ode –**curve fitting**org.apache.commons.math3.fitting –**function maximization or minimization**org.apache.commons.math3.optim –**genetic algorithms**org.apache.commons.math3.genetics –**machine learning (clustering and neural networks)**org.apache.commons.math3.ml –**common math/stat functions extending java.lang.Math**org.apache.commons.math3.util –**special functions (Gamma, Beta)**org.apache.commons.math3.special –**complex numbers**org.apache.commons.math3.complex –**rational numbers**org.apache.commons.math3.fraction –**

The package *org.apache.commons.math3.stat* provides several tools for statistical computations. For example, to compute mean, standard deviation, and many more, we can use *DescriptiveStatistics*:

```
double[] values = new double[] {65, 51 , 16, 11 , 6519, 191 ,0 , 98, 19854, 1, 32};
DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics();
for (double v : values) {
descriptiveStatistics.addValue(v);
}
double mean = descriptiveStatistics.getMean();
double median = descriptiveStatistics.getPercentile(50);
double standardDeviation = descriptiveStatistics.getStandardDeviation();
```

In this package, we can find tools for computing the covariance, correlation, or to perform statistical tests (using *TestUtils*).

In core Java, *Math.random()* can be used for generating random values, but these values are uniformly distributed between 0 and 1.

Sometimes, we want to produce a random value using a more complex distribution. For this, we can use the framework provided by *org.apache.commons.math3.distribution*.

Here is how to generate random values according to the normal distribution with the mean of 10 and the standard deviation of 3:

```
NormalDistribution normalDistribution = new NormalDistribution(10, 3);
double randomValue = normalDistribution.sample();
```

Or we can obtain the probability *P(X = x)* of getting a value for discrete distributions, or the cumulative probability *P(X <= x)* for continuous distributions.

Analysis related functions and algorithms can be found in *org.apache.commons.math3.analysis*.

A root is a value where a function has the value of 0. Commons-Math includes implementation of several root-finding algorithms.

Here, we try to find the root of *v -> (v * v) – 2* :

```
UnivariateFunction function = v -> Math.pow(v, 2) - 2;
UnivariateSolver solver = new BracketingNthOrderBrentSolver(1.0e-12, 1.0e-8, 5);
double c = solver.solve(100, function, -10.0, 10.0, 0);
```

First, we start by defining the function, then we define the solver, and we set the desired accuracy. Finally, we call the *solve()* API.

The root-finding operation will be performed using several iterations, so it's a matter of finding a compromise between execution time and accuracy.

The integration works almost like root finding:

```
UnivariateFunction function = v -> v;
UnivariateIntegrator integrator = new SimpsonIntegrator(1.0e-12, 1.0e-8, 1, 32);
double i = integrator.integrate(100, function, 0, 10);
```

We start by defining a function, we choose an integrator among the available integration solutions existing, we set the desired accuracy, and finally, we integrate.

If we have a linear system of equations under the form AX = B where A is a matrix of real numbers, and B a vector of real numbers – Commons Math provides structures to represent both the matrix and the vector, and also provide solvers to find the value of X:

```
RealMatrix a = new Array2DRowRealMatrix(
new double[][] { { 2, 3, -2 }, { -1, 7, 6 }, { 4, -3, -5 } },
false);
RealVector b = new ArrayRealVector(n
ew double[] { 1, -2, 1 },
false);
DecompositionSolver solver = new LUDecomposition(a).getSolver();
RealVector solution = solver.solve(b);
```

The case is pretty straightforward: we define a matrix *a* from an array of array of doubles, and a vector *b* from an array of a vector.

Then, we create an *LUDecomposition* which provides a solver for equations under the form AX = B. As its name states it, *LUDecomposition* relies on the LU decomposition, and thus works only with square matrices.

For other matrices, different solvers exist, usually solving the equation using the least square method.

The package *org.apache.commons.math3.geometry* provides several classes for representing geometrical objects and several tools to manipulate them. It is important to note that this package is divided into different sub-packages, regarding of the kind of geometry we want to use:

It is important to note that this package is divided into different sub-packages, regarding of the kind of geometry we want to use:

1D Euclidean geometry**org.apache.commons.math3.geometry.euclidean.oned –**2D Euclidean geometry**org.apache.commons.math3.geometry.euclidean.twod –**3D Euclidean geometry**org.apache.commons.math3.geometry.euclidean.threed –**1D spherical geometry**org.apache.commons.math3.geometry.spherical.oned –**2D spherical geometry**org.apache.commons.math3.geometry.spherical.twod –**

The most useful classes are probably *Vector2D*, *Vector3D*, *Line*, and *Segment*. They are used for representing 2D vectors (or points), 3D vectors, lines, and segments respectively.

When using classes mentioned above, it is possible to perform some computation. For instance, the following code performs the calculation of the intersection of two 2D lines:

```
Line l1 = new Line(new Vector2D(0, 0), new Vector2D(1, 1), 0);
Line l2 = new Line(new Vector2D(0, 1), new Vector2D(1, 1.5), 0);
Vector2D intersection = l1.intersection(l2);
```

It is also feasible to use these structures to get the distance of a point to a line, or the closest point of a line to another line (in 3D).

Commons-Math also provides some tools and algorithms for more complex tasks related to optimization and machine learning.

Optimization usually consists of minimizing or maximizing cost functions. Algorithms for optimization can be found in *org.apache.commons.math3.optim* and *org.apache.commons.math3.optimimization*. It includes linear and nonlinear optimization algorithms.

We can note that there are duplicate classes in the *optim* and *optimization* packages: the *optimization* package is mostly deprecated and will be removed in the Commons Math 4.

Genetic algorithms are a kind of meta-heuristics: they are a solution to finding an acceptable solution to a problem when deterministic algorithms are too slow. An overview of genetic algorithms can be found here.

The package *org.apache.commons.math3.genetics* provides a framework to perform computations using genetic algorithms. It contains structure that can be used to represent a population and a chromosome, and standard algorithms to perform mutation, crossover, and selection operations.

The following classes give a good start point:

*GeneticAlgorithm –*the genetic algorithm framework*Population –*the interface representing a population*Chromosome –*the interface representing a chromosome

Machine learning in Commons-Math is divided into two parts: clustering and neural networks.

The clustering part consists of putting a label on vectors according to their similarity regarding a distance metric. The clustering algorithms provided are based on the K-means algorithm.

The neural network part gives classes to represent networks (*Network*) and neurons (*Neuron*). One may note that the provided functions are limited compared to the most common neural network frameworks, but it can still be useful for small applications with low requirements.

*FastMath* is a static class located in *org.apache.commons.math3.util* and working exactly like *java.lang.Math*.

Its purpose is to provide, at least the same functions that we can found in *java.lang.Math*, but with faster implementations. So, when a program is heavily relying on mathematical computations, it is a good idea to replace calls to *Math.sin()* (for instance) to calls to *FastMath.sin()* to improve the performance of the application. On the other hand please note that *FastMath* is less accurate than *java.lang.Math.*

Commons-Math provides standard mathematical functions that are not implemented in *java.lang.Math* (like factorial). Most of these functions can be found in the packages *org.apache.commons.math3.special* and *org.apache.commons.math3.util*.

For instance, if we want to compute the factorial of 10 we can simply do:

```
long factorial = CombinatorialUtils.factorial(10);
```

Functions related to arithmetic (*gcd*, *lcm*, etc.) can be found in *ArithmeticUtils*, and functions related to combinatorial can be found in *CombinatorialUtils*. Some other special functions, like *erf*, can be accessed in *org.apache.commons.math3.special*.

It is also possible to handle more complex types using commons-math: fraction and complex numbers. These structures allow us to perform specific computation on this kind of numbers.

Then, we can compute the sum of two fractions and display the result as a string representation of a fraction (i.e. under the form “a / b”):

```
Fraction lhs = new Fraction(1, 3);
Fraction rhs = new Fraction(2, 5);
Fraction sum = lhs.add(rhs);
String str = new FractionFormat().format(sum);
```

Or, we can quickly compute power of complex numbers:

```
Complex first = new Complex(1.0, 3.0);
Complex second = new Complex(2.0, 5.0);
Complex power = first.pow(second);
```

In this tutorial, we presented a few of the interesting things you can do using Apache Commons Math.

Unfortunately, this article can't cover the whole field of analysis or linear algebra, and thus, only provides examples for the most common situations.

However, for more information, we can read the well-written documentation, which provides a lot of details for all aspects of the library.

And, as always, the code samples can be found here on GitHub.