Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using modulus operator to keep within indices of container

Tags:

c++

math

modulo

Assume I have a vector v with m elements in it, and a random access index to the vector called i.

When I increment the index, if it goes out of bounds, I want to index the first (zeroth) element. Similarly, when I decrement the index, if the index is < 0, I want to index to last element. At the moment I'm only moving through the container one element at a time, so came up with this function:

unsigned int GetIndexModM(int index,unsigned int m) {return (index + m) % m;}

The call-site might look like this:

std::vector<Whatever> v = ... // initialise with 5 elements
unsigned int i = 0;
unsigned int j = GetIndexModM(static_cast<int>(i) - 1,v.size()); // get preceeding index

This function will fail however if one subtracts a value > m from index:

unsigned int j = GetIndexModM(static_cast<int>(i) - 17,v.size()); // oops: returns -2

My question: What's the most elegant implementation of a function that takes any integer and returns it's place as an index?

like image 761
PeteUK Avatar asked Jul 20 '11 16:07

PeteUK


1 Answers

The trick for handling MOD is this, which works with positive as well as negative numbers:

  val = ((val % mod_val) + mod_val) % mod_val; 

For example, assume we want to keep value between 0 and 359 inclusive. We could use this:

  val = ((val % 360) + 360) % 360; 

Here's a simple example in C++.

int getmod(int val, int mod) {
  return ((val % mod) + mod) % mod; 
}

int main() {
  printf("%d\n", getmod(50,360));   // prints 50
  printf("%d\n", getmod(-400,360)); // prints 320
  printf("%d\n", getmod(350,360));  // prints 350
  printf("%d\n", getmod(375,360));  // prints 15
  printf("%d\n", getmod(-725,360));  // prints 355


  return 0;
}
like image 133
dcp Avatar answered Oct 13 '22 22:10

dcp