To Infinity and Beneath: Unreasonably Big Calculations in JavaScript | by Simon Haines

Published on November 9, 2022

Take a good look at your laptop. What’s going on in there? It’s a marvel, it really is. Your companion in getting things done, your partner in productivity! It is your wand, your Nimbus 2000, your Pantalaimon! Thinking with your brain is like taking a walk through a lovely park; thinking with a computer is like driving through it in a Lamborghini. Both are fun, but for different reasons.

Let’s put it to work and explore something computers are great at: really, really big calculations.
 

Approaching Infinity


When you were a kid, did you ever try and count as high as you could? If you were persistent, you probably got bored between one and two hundred. But you knew you could keep going if you wanted to. Where do you get when you keep going? We all know the answer: infinity!

1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + …

To implement this in JavaScript, we could do something like this:

But what if we counted in a different way? Not adding 1 each time, but adding something smaller and smaller. Each time we add something new, we halve it first.

1 + 1/2 + 1/4 + 1/8 + 1/16 + ...

Do we still get to infinity? Maybe so, maybe not! Let’s explore!

 

Adding Halves

Try setting this function up and running it with different numbers of terms. You should see we get:

1, 1.5, 1.75, 1.875, 1.9375, 1.96875, …

Are we ever going to get bigger than 2?! With 53 terms, JavaScript tells us the answer is:

1.9999999999999998

And with 54 terms it gives up and just says 2 is the answer. The answer is not 2, but JavaScript can’t cope with long decimals so it just rounded for us. What we need is arbitrary precision. Fortunately, there are libraries for that, like Big.js. With a few changes, we’re good to go!

Now, calling our function to add up 54 terms in our sum, we get an answer of:

1.99999999999999988897769753748434595763683319091796875

But why stop there? Let’s take this thing for a spin. 10000 terms in our sum, with 4000 decimals of precision:

In all its glory:

1.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999899752545015870959814048881325140445013568644373231483211571419154415209380984319196217786075031551732769563014275883255837345113646217453967035662090408437628251581777678775421230244319578663732452894783795008420855674057521182017195454203041915613024187657381045490281558178359479253348541966650993835105211510613591894266811538200955696615502838042640970253680783515723843909169832242226596695392015525373792271600364930732315424558789034487099352925766131512692534925611347596222113012001929439051660564898954149100933638862047025120402015344952231695285277884662901854639428036151269250853506061580928772036109553272308588645995719951881022856294994606744293379705554055971193541842764633939370875266848900727912880101935269885497394886353037259019383377911006521936904298471378058145505956237624863034314247030621546923560995222669575256581536154840881099007918191012926368095735244304596451644477571563635798645717867488163004667800014854988191901335507050296766460492053811910231984

By now, I’m pretty convinced that this sum will never exceed 2, but it will keep getting closer and closer forever!

We might be tempted to make another conclusion:

If we’re adding up infinitely many numbers, we won’t get to infinity if the numbers we’re adding keep getting smaller and smaller.

Let’s finish by blowing this idea to pieces.
 

Adding Fractions


What if we added up the fractions with a 1 on top? Like this:

1 + 1/2 + 1/3 + 1/4 + 1/5 + ...

The number we’re adding keeps getting smaller and smaller, so perhaps this sum will get stuck at some upper limit, a bit like adding halves. Let’s give it a go:  

Here’s what we get:

Up to

Sum

1 + 1/2

1.5

1 + 1/2 + 1/3  + 1/4

2.083333...

1 + 1/2 + ... + 1/8 

2.71785714285714285714

1 + 1/2 + ... + 1/16

3.38072899322899322899

1 + 1/2 + ... + 1/32

4.05849519543652010277

1 + 1/2 + ... + 1/64

4.74389090370576902603

1 + 1/2 + ... + 1/128

5.433147092589172277

 

Interestingly, if we keep adding more terms, the sum seems to keep getting bigger. In fact, if we double the number of terms, the sum seems to grow by something like 0.6 each time. If we kept adding more and more terms, the sum would keep growing and growing, ever so slowly, to reach infinity. This is very different behaviour from the adding halves function and not at all what we expected.
 

Why?!
 

We need to step away from the computer for a moment to answer this. Machines are great at showing us patterns that we might otherwise miss, but not great at explaining them. Let’s look at the sum

1 + 1/2 + 1/3 + 1/4 + 1/5 + ...

in more detail. We can group the terms together so we’re taking 1 at a time, then 2 at a time, then 4 at a time, and so on, like this: What do we notice?

1 + 1/2 + (1/3 + 1/4) + (1/5 + 1/6 + 1/7 + 1/8) + ...
 

Terms 

What do we notice?

1

Is 1

+ 1/2

Is ½ 

+ 1/3 + 1/4

2 terms, each is  >= 1/4

+ 1/5 + 1/6 + 1/7 + 1/8

4 terms, each is >= 1/8

+ 1/9 + ... + 1/16

8 terms, each is >= 1/16

+ 1/17 + ... + 1/32

16 terms, each is >= 1/32

... and so on

… and so on

 

so our addFrac() sum would be larger than

1 + 1/2 + (2 * 1/4) + (4 * 1/8) + (8 * 1/16) + ...

which is

1 + 1/2 + 1/2 + 1/2 + 1/2 + ...

So, mysteriously, addFrac() behaves a lot more like addOnes() than addHalves()!


Conclusions


We saw that, just because we have infinitely many things to add up, it doesn’t mean we get to infinity! Sometimes we get stuck under a particular upper limit. Nevertheless, we can still reach infinity (very slowly) by adding up terms which get smaller and smaller.

Our computers can perform huge calculations for us, to help us validate our ideas, or to spot the right pattern before we go and seek an explanation for them. But we shouldn’t draw conclusions from limited data: it wasn’t obvious that the addFrac() would climb up slowly to infinity after we saw the behaviour of the addHalves() function.

Go and take your motherboard for a spin and see what else you can find!
 

Simon Haines is a Software Engineering Coach at Multiverse.