Necesito escribir un número entero que "circule" entre un valor mínimo y máximo. Si se alcanza el valor máximo y agrega 1, salta al valor mínimo. Si resta 1 del valor mínimo, alcanza el valor máximo.


Ejemplo:
Valor mínimo = 2;
maxValue = 10;

Conduce a: ... 2,3,4, ... 9,10,2,3, ...


Descubrí el algoritmo de suma, pero estoy atascado con la resta. La adición se ve así:

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);
}

Básicamente, el algoritmo se puede dividir en "newValue% range". Todo el + - minValue es solo para eliminarlo del cálculo y agregarlo más tarde nuevamente.

¿Existe un algoritmo conocido para esto? Si no, ¿tienes una idea de cómo podría ser el algoritmo de resta?

3
Meister der Magie 9 may. 2020 a las 23:34

3 respuestas

La mejor respuesta

Comience aplicando el módulo a b y restando el mínimo de a.value

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

Además, agregue b a value y aplique el módulo

int result = (value+b) % range;

Para restar, agregue range a value antes de restar b, y aplique el módulo. Esto funciona porque (value+range) % range == value por lo que agregar el rango no cambia el resultado final, pero evita que el resultado intermedio sea negativo.

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

Termine agregando el mínimo de nuevo en

int circularValue = result + a.minValue;

Aquí está el código final, cortesía de @Meister der Magie

Adición:

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+b) % range;

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

Sustracción:

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);
}
2
user3386109 9 may. 2020 a las 21:51

Sustitución

int sum = a.value + b;

Con

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

Dónde

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

Debería funcionar bien!

0
nikhilbalwani 9 may. 2020 a las 20:53

Esto debería darle una idea para la fórmula:

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;
}

Salida:

AddCircular(2,-1);
10
AddCircular(10,1);
2
0
Optimax 9 may. 2020 a las 20:52