3

I need to write an integer that "circulates" between a minimum and maximum value. If the maximum value is reached and you add 1, it jumps to the minimum value. If you subtract 1 from the minimum value you reach the maxValue.


Example:
minValue = 2;
maxValue = 10;

leads to: ... 2,3,4,...9,10,2,3,...


I figured out the addition algorithm, but I'm stuck with the subtraction. Addition looks like this:

public static circularInt operator +(circularInt a, int b)
{
    int sum = a.value + b;        
    int circularValue = ((sum - a.minValue) % (a.maxValue + 1 - a.minValue)) + a.minValue;

    return new circularInt(circularValue, a.minValue, a.maxValue);
}

Basically the algorithm can be broken down to "newValue % range". All the +- minValue is just to eliminate it from the calculation, and add it later on again.

Is there a known algorithm for this? If not, do you have an idea how the subtraction algorithm might look like?

user3386109
  • 34,287
  • 7
  • 49
  • 68

3 Answers3

3

Start by applying the modulo to b and subtracting the minimum from a.value

int range = a.maxValue + 1 - a.minValue;
b %= range;
int value = a.value - a.minValue;

Allowing for negative values, b will now be greater than -range and less than range.

For addition, add b and the range to the value, and apply the modulo. Adding the range is necessary when b is a negative number. Adding a negative number is the same as subtracting a positive number.

int result = (value+range+b) % range;

For subtraction, add the range to the value before subtracting b, and apply the modulo. This works because (value+range) % range == value so adding the range doesn't change the final result, but it does keep the intermediate result from going negative.

int result = (value+range-b) % range;

Finish by adding the minimum back in

int circularValue = result + a.minValue;

Here's the final code, courtesy of @Meister der Magie

Addition:

public static circularInt operator +(circularInt a, int b)
{
    int range = (a.maxValue + 1 - a.minValue);
    b %= range;
    int value = a.value - a.minValue;

    int additionResult = (value+range+b) % range;

    int circularValue = additionResult + a.minValue;
    return new circularInt(circularValue, a.minValue, a.maxValue);
}

Subtraction:

public static circularInt operator -(circularInt a, int b)
{
    int range = (a.maxValue + 1 - a.minValue);
    b %= range;
    int value = a.value - a.minValue;

    int subtractionResult = (value+range-b) % range;

    int circularValue = subtractionResult + a.minValue;
    return new circularInt(circularValue, a.minValue, a.maxValue);
}
user3386109
  • 34,287
  • 7
  • 49
  • 68
0

Replacing

int sum = a.value + b;

with

int sum = (a.value - b + ( (b / range) * range) );

where

int range = a.maxValue + 1 - a.minValue;

should work fine!

nikhilbalwani
  • 817
  • 7
  • 20
  • Nope, that's what I thought at first. But it doesn't return values between minValue and maxValue. – Meister der Magie May 09 '20 at 20:45
  • though it wont return values between minvalue and maxvalue, after doing % (a.maxValue + 1 - a.minValue), it will be in the range. pls check – nikhilbalwani May 09 '20 at 20:50
  • @nikhilbalwani [mod of negative number](https://stackoverflow.com/questions/1082917/mod-of-negative-number-is-melting-my-brain) – Guru Stron May 09 '20 at 20:51
0

This should give you an idea for the formula:

private const int MinValue = 2;
private const int MaxValue = 10;

public static int AddCircular(int a, int b)
{
    int modulo = MaxValue - MinValue + 1;
    int sum = (a - MinValue + b) % modulo + MinValue;
    if (sum < MinValue) sum += modulo;
    return sum;
}

Output:

AddCircular(2,-1);
10
AddCircular(10,1);
2
Optimax
  • 1,534
  • 2
  • 16
  • 23