Monday, May 14, 2012

Java's Modulo Function--Wrapping Around

I've previously discussed operators in Java, where I gave a brief introduction to the modulo operator, %.

The percent sign is used in many computer languages as a brief, single-character symbol for the remainder of a division, not for a percentage of a number, as you might expect.

What's Left Over

In many calculations in normal day to day life, the remainder of a division is not very important. It's just the odd change left over at the end of doing division. With computer programs, however, modulos can be very useful and powerful.

One of its most important uses is to limit the range of a value. For example, if we're only interested in having a value be a number from 0 to 99, and any value over that is something we don't want, we can use modulo as a way of cutting any number we get down to size. Since the remainder of a division can never be as large or larger than the divisor, we know that any remainder from a division by 100 can never be more than 99 (in integers.) So we can take any number, find the modulo by some number that we want as an unreachable cap on our values, and never get a number that's too big.

limitedNumber = someNumber % 100

limitedNumber will never be higher than 99.

Real World Analogies

A real world version of this is a knob that you can turn around without a stop on it. The knob's setting can vary over a range of values all the way around it. But when you turn it past some point, it goes from its highest setting to its lowest setting.
Radio dial, image by John McComb of Oakland, CA.

For example, a radio dial that goes up in frequency until you hit the top of the radio band, then starts tuning over again from the bottom of the band.

Computer Applications

One of the most common uses of the modulo in computer programs uses that same ability with computer graphics. How many computer games have you seen where an object goes off one side of the computer's screen then reappears on the other side? That's an example of the modulo function. Let's look at an asteroid object that has its horizontal location on screen tracked by the member variable xLoc (short for x location):

Class Asteroid{
    int xLoc, yLoc, xSpeed, ySpeed, size;

We'll assume the class has all the methods it needs to do what Asteroids do. Our instance is:

Asteroid asteroid = new Asteroid();
(If this is unfamiliar to you, you may want to read Creating a Java Variable, Two Steps.)

Now let's say our asteroid is presented on a screen area that is 800 pixels wide and 600 pixels high. That means our xLoc value can vary from 0 (the leftmost location on screen) to 799 (the rightmost location on screen) since we have a screen area 800 pixels wide. Remember, when we start counting at 0 our highest number is one less than the total number of pixels.

We can move our asteroid from left to right as follows:

xLoc = xLoc + xSpeed;

Where xSpeed is how fast we're moving across the screen.

The problem is, what do we do when we hit the right edge of the screen? That is, what do we do when xLoc is higher than 799?

If we want our asteroid to "wrap around" from the right side to the left side of our screen, the modulo operator is just what we want. We can do this to make it wrap around that way:

xLoc = xLoc + xSpeed;
xLoc = xLoc % 800; // Hard-coded screen width, for now.

That will make xLoc always be from 0 (when there is a zero remainder) to 799 (the highest possible remainder when dividing by 800.)

We might have a method in Asteroid like the following:

public int moveHoriz(int howFar){
  // Moves the Asteroid horizontally by howFar pixels on an 800 pixel wide screen.
  // returns the new pixel location.
  return (xLoc + howFar) % 800;

This glosses over a few other problems (like going from the left edge of the screen to the right), but illustrates the use of modulo to bring the object around from right to left again.

An Expanded Example

Here's a more developed example that deals with speeds higher than the screen width, and wraps both ways:

public int moveHoriz(int howFar){
  // Moves the Asteroid horizontally by howFar pixels on a screen.
  // It returns the new horizontal pixel location.

  // We have a screen width available to us in member variable xWidth,
  // and our x location in xLoc.
  // Wraps from right to left, or left to right.

  //Use modulo to trim speed if it's too high.
  if (howFar > xWidth) howFar %= xWidth;

  // Calculate the new x location and return it.
  return (xLoc + howFar + xWidth) % xWidth;

Radio Dial image by John McComb.