Lorah Attkins
Lorah Attkins

Reputation: 5856

Rotate through a zero based range for positive and negative numbers

Say I have a zero-based range like

[0, 1, 2, 3, 4]

these are essentially the indexes of an array with size = 5. Is it possible to use a signed integer variable to continuously loop up or down in that range?

By up or down, I mean that the variable is permitted to perform arbitrarily many increment or decrement operations:

++index;
--index;
index += offset;
index -= offset;

So for example decrementing the index should map to following values:

index = 2;

while (/*...*/)
{
  --index;
  index_in_range(index, 5);
}

The function index_in_range(index, 5) would output:

1, 0, 4, 3, 2, 1, 0, 4, 3, 2, 1, .... and so on

The positive case is just a modulo operation over the range size, but for the negative I can't figure out how the mapping goes.

EDIT :

The requested function index_in_range(int idx, int range) takes an arbitrary integer, i.e. could be called as index_in_range(-245, 14). The example given does use a decrement operator but I never said I'm only offsetting by one each time.

Upvotes: 0

Views: 261

Answers (2)

Mohaned El-haddad
Mohaned El-haddad

Reputation: 139

To increase

index = (index+1)%size;

To decrease

index = (index-1+size)%size

Upvotes: 1

Sneftel
Sneftel

Reputation: 41513

C made a really poor decision for % to round towards zero, rather than be a straightforward floor, so the math's clunkier than it has to be. Basically, though, you want (index % size + size) % size. That code starts by chopping off the negative or positive multiples to bring the index into the range (-size, size), adds size to map it into (0,size*2), and a final % to map it into [0,size).

If size is not known at compile time, it's likely more performant to replace everything after the first modulus with a conditional: index %= size; if(index < 0) index += size;.

Upvotes: 1

Related Questions