Say we have a linear function of the form f(x) = mx + b and we want to apply that function some number of times starting with some initial value. It’s easy to write a function to do this:

def apply_transformation_repeatedly(init, mult, plus, reps):
    x = init

    for _ in range(reps):
        x *= mult
        x += plus

    return x

As an example, let the initial value be 1 and the linear function be 2x + 3, and say we want to apply that function four times. The result is 61, no problem.

Now let the function and the initial value be the same, but instead of applying the function four times, we want to apply it four billion times.

You might ask, “Why on Earth would anyone want to do that? Shouldn’t the presence of such a farcically large parameter be treated as a sign that we’re on the wrong path? Wouldn’t we be better off trying to rethink our problem?” If I were you, I would stop asking stupid questions and get cracking on that computation, because four billion iterations is going to take a while.

The parameters aren’t the problem; the problem is that the straightforward programming solution won’t work. What’s required here is real math. Anyone who doesn’t know real math won’t be able to solve this. Try pitching this problem to the smartest programmer you can think of who doesn’t know real math. Within a minute they will be saying “Uhhhh”. They will try to program their way out of it, and they will fail.

There is no way around it: solving this problem requires the use of the geometric series formula:

def apply_transformation_repeatedly(init, mult, plus, reps):
    return (
        init
        * (term := mult ** reps)
        + (plus * (1 + ((term - mult) // (mult - 1))))
    )

And it works like magic! Of course, it’s isn’t actually magic, and someone who knows real math can explain and prove how it works. But without such a proof, it may as well be magic. According to this formula, starting with 1 and applying 2x + 3 four billion times works out to approximately 101204119983 (a number with 1.2 billion digits).

Obviously it would be best to know real math. And if wishes were horses, beggars would ride. So without such knowledge, what is a programmer to do?

After actually knowing real math, the next best thing is recognizing when a real math solution exists. When faced with a seemingly insurmountable numerical problem, this means stopping and saying “Surely someone has come across this problem before and worked out a formula.” What are the chances that I am the first person ever to try repeatedly applying a linear function to some initial value? No, somebody else has tried it, and it’s a generally a safe bet that they found a solution.

After assuming that a real math solution exists, you can go find someone who knows real math and ask them. A more advanced alternative is to thumb through the back pages of a math textbook until you find a formula that looks like it’s applicable.