Wrap Around Increments

21st June 2020

Something I've been writing long hand for a number of years is wrap around increments. This is essentially adding to a value that has an upper limit, and wrapping back to 0 when that max value is reached.

This can be done with an if statement, in this case I'm using PHP, but the idea is the same in other languages.

  1. /**
  2.  * Increment within a upper bound.
  3.  *
  4.  * @param int $number
  5.  * The number to increment.
  6.  * @param int $max
  7.  * The upper bound of the number.
  8.  *
  9.  * @return int
  10.  * The bounded incremented number.
  11.  */
  12. function boundedIncrement($number, $max) {
  13. $number++;
  14. if ($number > $max) {
  15. $number = 0;
  16. }
  17. return $number;
  18. }

This function can be used simply enough, for example, if we try to increment a number that is at the maximum bound value then the function will return 0.

echo boundedIncrement(500, 500); // prints 0

A simpler approach to this using pure maths is to use a neat modulus trick, which I found recently.

By adding the incremented value to the maximum value and then performing a modulus calculation on the maximum we essentially automatically wrap around to 0 again. Note that in order to wrap around to the start correctly we need to add 1 to the max value.

Here is the new function, which works in the same way as the previous one in that we can't increment above the value of the max number.

  1. /**
  2.  * Increment within a upper bound.
  3.  *
  4.  * @param int $number
  5.  * The number to increment.
  6.  * @param int $max
  7.  * The upper bound of the number.
  8.  *
  9.  * @return int
  10.  * The bounded incremented number.
  11.  */
  12. function boundedIncrement($number, $max) {
  13. return (($number + 1) + ($max + 1)) % ($max + 1);
  14. }

Similar to this, we can also decrement in the same way. In this case when we reach 0 the number will loop back to the max number again.

  1. /**
  2.  * Decrement within an upper bound.
  3.  *
  4.  * @param int $number
  5.  * The number to decrement.
  6.  * @param int $max
  7.  * The upper bound of the number.
  8.  *
  9.  * @return int
  10.  * The bounded decremented number.
  11.  */
  12. function boundedDecrement($number, $max) {
  13. return (($number - 1) + ($max + 1)) % ($max + 1);
  14. }

Here are some tests of these functions in action.

  1. echo boundedIncrement(0, 500); // prints 1
  2. echo boundedIncrement(1, 500); // prints 2
  3. echo boundedIncrement(250, 500); // prints 251
  4. echo boundedIncrement(499, 500); // prints 500
  5. echo boundedIncrement(500, 500); // prints 0
  6.  
  7. echo boundedDecrement(0, 500); // prints 500
  8. echo boundedDecrement(1, 500); // prints 0
  9. echo boundedDecrement(250, 500); // prints 249
  10. echo boundedDecrement(499, 500); // prints 498
  11. echo boundedDecrement(500, 500); // prints 499

One quirk of this method is that we can actually send numbers that are outside of the bounded range and still receive a number that makes sense. This isn't covered by the simple if statement function that we started with.

  1. echo boundedIncrement(501, 500); // prints 1
  2. echo boundedIncrement(600, 500); // prints 100
  3.  
  4. echo boundedDecrement(501, 500); // prints 500
  5. echo boundedDecrement(600, 500); // prints 98

We can enhance these functions by adding a parameter that allows us to change the amount of increment.

  1. /**
  2.  * Increment within a upper bound.
  3.  *
  4.  * @param int $number
  5.  * The number to increment.
  6.  * @param int $max
  7.  * The upper bound of the number.
  8.  * @param int $delta
  9.  * The number to increment by.
  10.  *
  11.  * @return int
  12.  * The bounded incremented number.
  13.  */
  14. function boundedIncrement($number, $max, $delta = 1) {
  15. return (($number + $delta) + ($max + 1)) % ($max + 1);
  16. }
  17.  
  18. /**
  19.  * Decrement within an upper bound.
  20.  *
  21.  * @param int $number
  22.  * The number to decrement.
  23.  * @param int $max
  24.  * The upper bound of the number.
  25.  * @param int $delta
  26.  * The number to decrement by.
  27.  *
  28.  * @return int
  29.  * The bounded decremented number.
  30.  */
  31. function boundedDecrement($number, $max, $delta = 1) {
  32. return (($number - $delta) + ($max + 1)) % ($max + 1);
  33. }

These functions (and the maths behind them) are useful when looking at producing graphics or cellular automata. It allows us to loop around from top to bottom or from left to right without having lots of if statements in the code. Also, because this is just using a mathematical method to perform the wrap around it is actually quicker than running if statements.

Add new comment

The content of this field is kept private and will not be shown publicly.