Recently I’ve gotten interested in experimental mathematics – finding mathematical relations using computational methods, rather than a mathematicians insight. While I won’t discuss the philosophical ramifications of this, I do want to detail a method for finding near-integers using experimental mathematics.

### Near-integers

A near-integer is a number which is “close” to being a integer, within some . Finding near-integers is easy, the number is *almost* equal to 1, but it’s not *interesting*. The fun part about near-integers is that a seemingly random relation somehow almost equals an integer.

For instance, , which is arguably close to being -1. While there is no rigorous definition of what is a near-integer, we will be satisfied with finding the relation which is “closest” to being an integer (more on this later).

### Finding near-integers

In the first part of this post we’ll deal with the basic principles of the algorithm, and further on we’ll get more technical.

So, the basic principle is that we’ll generate a random expression, and check whether or not it’s close to being an integer. Then we’ll repeat this process for 100.000 random expressions and choose the expression which was closest to being an integer. Put in bullet points:

- Set iterator , and so far best expression .
- Generate random expression .
- If is closer to being an integer than , set .
- Increment by one.
- If go to step 2.
- Display expression .

The process of generating expressions sounds simple, but it is, in fact, not that simple to generate a random expression, as we’ll discuss later on.

One of the more prominent results from my program is the following:

In fact, this number is closer to being an integer than .

Another interesting result is:

Where .

For more results check the bottom of this post.

### Modelling the expressions

To be able to use our clever new algorithm, we need to be able to generate expressions. But what is an expression? An expression is a mathematical statement which returns some value. In practice, we’ll model an expression as an *abstract class* in Java. An abstract class is a class, which contains some fundamental, abstract functions and methods that can be inherited by other subclasses.

This is useful, because it allows us to model an abstract class called *Expression*, and have subclasses of this, which perform specific functions. Their common function is *getValue();*, so all subclasses of *Expression *needs to be able to return a numeric value. The most basic expression is *Constant*, which returns a single number. An example of *Constant *could be the number 1, the number 2, or .

Next up we could have a class called *Addition*, which takes two other *Expression*‘s and returns their sum when *getValue(); *is called. Similarily, we have *Subtraction, Multiplication, Division*, and *Exponentation*. It’s also easy to implement other functions, but as of now they won’t be necessary.

The reason we use abstract classes is so we can have more complicated, nested expressions inside each other. So, an instance of *Addition *contains two expressions, which might also be other *Addition *classes.

To make things more explicit, let’s take a look at the structure of the expression . This expression is an instance of *Subtraction*, containing the two other expressions (being an instance of *Exponentation*), and (being an instance of *Constant*).

We can also implement other functions than *getValue();*. In my implementation, I have also made *getLaTeX();*, which returns the LaTeX-code for the expression, and *getString();*, which returns a more readable string representing the expression.

### Generating random expressions

To make a random expression, we’ll use recursion. We have a function *randomExpression(int depth); *which returns a new random expression. This function has two special cases:

**Depth = 0**

When the depth is 0, we’ll simply return a new *Constant *from some alphabet of constants. In practice we’ll use the alphabet .

**Depth > 0**

When the depth is larger than zero, we’ll return a new random binary expression (for instance *Addition*, which contains two other expressions.) with the arguments *randomExpression(depth-1), randomExpression(depth-1)*. This ensures that we’ll have a nested expression. A special clause is added for *Exponentation*, which returns an instance of *Exponentation*, with the arguments *randomExpression(0), randomExpression(0) *to avoid ugly towers of exponents.

This is the basic gist of it. This will generate a random expression of some depth.

### Closing remarks

While this method proves successful in finding interesting near-integers, most often it finds rather tedious near-integers. For instance, one of the near-integers I often encounter are like the following:

The program claims this is a near-integer close to 3 (obviously). This is unfortunate, but there is little to be done with it without some really sophisticated methods.

### Gallery of near-integers

Here is a list of all the most interesting near-integers I’ve found using this method. Some of the expressions have been simplified using Wolfram|Alpha.

**Error: **

**Error: **

**Error: **

**Error: **

**Error: **

**Error: **

Have you tried something like a local gradient descent? Say, start with a random expression, and then (viewing the expr as a tree) look at all possible ways to change a node of the tree. Pick the one that is closest to an integer and repeat. I imagine you might want to rule out expressions like , but it could still give some interesting results.

This sounds really interesting! Although, instead of finding the local maximum, I think I’m going to systematically go through all possible expressions (generate all trees) to find the global maximum for any given depth.

Unless this turns out to be computationally infeasible, in which case I’d probably try a local gradient descent instead 🙂

You’ll have to keep it pretty small. The number of labeled trees on n vertices is order n^n, and I imagine it would be similarly exponential given depth restrictions.

You’re right. After already removing lots of redundant vertices (discarding trees with e * e because we know we get e^2 etc.) I get the following growth:

* depth=0 – 13 expressions

* depth=1 – 180 expressions

* depth=2 – 22306 expressions

* depth=3 – takes more than 2 hours on my pc, unknown

I imagine a local gradient descent will be better!

cos(355) = 0.999 999 999 55 🙂

This makes sense, since 355/113 is a good rational approximation to pi.

103993 / 33102 is an even better approximation.

And cos(103993) = 0.999 999 999 82

I’ve put a simple GA code together – always nice to play god 🙂 My first interesting effort is 720 ln(3) / 113 = 7.0000075

Could you provide some more details? I’d love to try implementing this myself 🙂

Of course – it’s not all that far removed from what you did. I’ll put my (fairly horrible) code up on github later on for the world to laugh at.

Here’s my code: https://github.com/icecolbeveridge/nearlyint/

Feel free to offer suggestions / improvements.

I wondered if you were interested in finding functions capable of generating near integers such as “Hickerson series of almost integers” http://rosettacode.org/wiki/Hickerson_series_of_almost_integers

Interesting read!

I had actually accidently discovered this result with the golden ratio. In my program, I had discovered a bunch of near-integers, which were high powers of phi, getting increasingly closer to an integer the higher the exponent gets.

It’s nice to get an explanation as to why 🙂