# Bug report: Compute the 5 next months with modulo arithmetic

December 6, 2017This post is about a stupid bug I wrote and what I learned from it. The goal of this format is to reduce the chance repeating a mistake and possibly prevent someone else from making it entirely. I will try to write more of these posts because I inevitably will write more incorrect code. Some errors are simple and easy to explain while others are more subtle and require more context. The one I write about today belongs to the former type. In fact it is a pretty embarrassing one but that’s the whole point right?

*I encourage anyone to write this kind of post. If you do, please let me know so I can learn from your mistakes!*

## The problem

Given a month represented by a number between 1 and 12, compute the number representations of the 5 months following it. Here are a few example inputs and outputs:

$$ 5 \mapsto \{ 6,7,8,9,10 \} $$

$$ 8 \mapsto \{ 9,10,11,12,1 \} $$

$$ 12 \mapsto \{ 1,2,3,4,5 \} $$

It is a purely mathematical function that needs to be implemented. And a simple one indeed, but hey: I managed to get it wrong.

## The bug

Now comes the embarrassing part, here is my fairly old PHP code trying to implement this:

```
// Input month given in $month
$next_months = [];
for($i = 1; i < 6; ++i) {
$next_months[] = $month + $i % 13;
}
```

This is completely wrong. Probably the worst mistake is that I got operator precedence wrong: Modulus (`%`

) binds stronger than addition (`+`

). Therefore `$i % 13`

is evaluated first and will simply result in `$i`

because it is always smaller than `13`

. But even if you correct the order of operations with parentheses, the result will still be wrong. I honestly cannot remember how I came up with this, but I probably thought things will get refactored and cleaned up anyways. It often doesn't until things start to break.

## The fix

Since the error was purely mathematical, the fix is too. There are many other possible correct solutions involving PHP built in functions handling dates. However, I decided to keep this purely arithmetic. I simply wanted to know the mathematical function that I am trying to implement. It is enough to take a step back and realize that the function for the next month behaves almost like the **modulo 12** function. It maps an integer onto its remainder when divided by twelve:

\(x\) | 0 | 1 | 2 | \( \dots \) | 11 | 12 | 13 | 14 | \( \dots \) |
---|---|---|---|---|---|---|---|---|---|

\( x \mod 12 \) | 0 | 1 | 2 | \( \dots \) | 11 | 0 | 1 | 2 | \( \dots \) |

I say almost, because it is shifted by one. We do not have a month for the integer 0, but we do have one for 12. But that is just a matter of identifying things! So I can map the numbers representing months onto these by subtracting one. First I subtract one to get the corresponding number in the system above. Then I perform the modulo 12 operation and transform the result back into the original space by adding one:

$$

nextMonth(x) := ((x - 1) \mod 12 ) + 1

$$

The corresponding PHP code then becomes:

```
// Input month given in $month
$next_months = [];
for($i = 1; i < 6; ++i) {
$next_months[] = (($month - 1 + $i) % 12) + 1;
}
```

Again, I am not saying this is the best way to do this. At least for me it obviously is not, because I got it wrong the first time. The purpose of this post is to help me get modulo right the next time I need it.

And to realize that all code is error prone, even "trivial" things like this.