Wrap Around Increments

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.

/**
 * Increment within a upper bound.
 *
 * @param int $number
 *   The number to increment.
 * @param int $max
 *   The upper bound of the number.
 *
 * @return int
 *   The bounded incremented number.
 */
function boundedIncrement($number, $max) {
  $number++;
  if ($number > $max) {
    $number = 0;
  }
  return $number;
}

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.

/**
 * Increment within a upper bound.
 *
 * @param int $number
 *   The number to increment.
 * @param int $max
 *   The upper bound of the number.
 *
 * @return int
 *   The bounded incremented number.
 */
function boundedIncrement($number, $max) {
  return (($number + 1) + ($max + 1)) % ($max + 1);
}

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.

/**
 * Decrement within an upper bound.
 *
 * @param int $number
 *   The number to decrement.
 * @param int $max
 *   The upper bound of the number.
 *
 * @return int
 *   The bounded decremented number.
 */
function boundedDecrement($number, $max) {
  return (($number - 1) + ($max + 1)) % ($max + 1);
}

Here are some tests of these functions in action.

echo boundedIncrement(0, 500); // prints 1
echo boundedIncrement(1, 500); // prints 2
echo boundedIncrement(250, 500); // prints 251
echo boundedIncrement(499, 500); // prints 500
echo boundedIncrement(500, 500); // prints 0

echo boundedDecrement(0, 500); // prints 500
echo boundedDecrement(1, 500); // prints 0
echo boundedDecrement(250, 500); // prints 249
echo boundedDecrement(499, 500); // prints 498
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.

echo boundedIncrement(501, 500); // prints 1
echo boundedIncrement(600, 500); // prints 100

echo boundedDecrement(501, 500); // prints 500
echo boundedDecrement(600, 500); // prints 98

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

/**
 * Increment within a upper bound.
 *
 * @param int $number
 *   The number to increment.
 * @param int $max
 *   The upper bound of the number.
 * @param int $delta
 *  The number to increment by.
 *
 * @return int
 *   The bounded incremented number.
 */
function boundedIncrement($number, $max, $delta = 1) {
  return (($number + $delta) + ($max + 1)) % ($max + 1);
}

/**
 * Decrement within an upper bound.
 *
 * @param int $number
 *   The number to decrement.
 * @param int $max
 *   The upper bound of the number.
 * @param int $delta
 *  The number to decrement by.
 *
 * @return int
 *   The bounded decremented number.
 */
function boundedDecrement($number, $max, $delta = 1) {
  return (($number - $delta) + ($max + 1)) % ($max + 1);
}

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.
CAPTCHA
12 + 2 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.