The Quest for Near-Integers

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.


A near-integer is a number which is “close” to being a integer, within some \epsilon. Finding near-integers is easy, the number 1 + 10^{-20} 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, \sin(11) = - 0.9999990206..., 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:

  1. Set iterator i = 0, and so far best expression e_{best}.
  2. Generate random expression e.
  3. If e is closer to being an integer than e_{best}, set e_{best} = e.
  4. Increment i by one.
  5. If i < 100000 go to step 2.
  6. Display expression e_{best}.

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:

2 \cdot \pi \cdot (e + \pi) \cdot (e + \pi^e) \approx 927

In fact, this number is closer to being an integer than \epsilon = 2.1 \cdot 10^{-5}.

Another interesting result is:

-3 \cdot \pi \cdot (1 + e - 5\cdot \pi) \approx 113

Where \epsilon = 8.6 \cdot 10^{-5}.

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 \pi.

Next up we could have a class called Addition, which takes two other Expression‘s a, b 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 \pi^2 + 1. This expression is an instance of Subtraction, containing the two other expressions \pi^2 (being an instance of Exponentation), and 1 (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 \Sigma of constants. In practice we’ll use the alphabet \Sigma = \{ \pi, e, 1,2,3,4,5,6,7,8,9 \}.

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:

3 - \dfrac{\pi}{6^7}

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.

Expression: 4 \cdot e^{\pi} \cdot \pi ^{1 + e} \approx 6531

Error: \epsilon = 1.4 \cdot 10^{-5}

Expression: 2 \cdot \pi \cdot (e + \pi) \cdot (e + \pi^e) \approx 927

Error: \epsilon = 2.1 \cdot 10^{-5}

Expression: -3 \cdot \pi \cdot (1 + e - 5\cdot \pi) \approx 113

Error: \epsilon = 8.6 \cdot 10^{-5}

Expression: (6 + \pi) \cdot (6 - e) \approx 30

Error: \epsilon = 1.3 \cdot 10^{-4}

Expression: 3 \cdot e \cdot (4 - \pi) \approx 7

Error: \epsilon = 1.8 \cdot 10^{-4}

Expression: e + \pi + e^{\pi} \approx 29

Error: \epsilon = 5.6 \cdot 10^{-4}



13 thoughts on “The Quest for Near-Integers

  1. 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 n - 1/k, but it could still give some interesting results.

    1. 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 🙂

      1. 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.

      2. 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!

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

      1. 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.

    1. 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 🙂

Comment on this article

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s