I guess the solution for this is quite simple, but I've been thinking about it for a while and couldn't come up with an elegant solution.
I have a range of numbers, e.g. 1..10 = (1,2,3,4,5,6,7,8,9,10)
, which is circular, meaning the number after the last one is again the first one (next(10)=1
).
For a given number i>0
in the range, I would like to calculate the next m
-th, and previous m
-th number. e.g. next(5,1)=6
next(10,1)=1
next(10,2)=2
prev(5,2)=3
prev(1,1)=10
prev(1,2)=9
.
For next
I can just take (i+m)%n
where n
is the length of the range (n=10
in the example). But for prev
I couldn't find an elegant solution.
The range of values for an integer modulo operation of n is 0 to n − 1 inclusive (a mod 1 is always 0; a mod 0 is undefined, possibly resulting in a division by zero error in some programming languages). See Modular arithmetic for an older and related convention applied in number theory.
The modulus of a negative number is found by ignoring the minus sign. The modulus of a number is denoted by writing vertical lines around the number. Note also that the modulus of a negative number can be found by multiplying it by −1 since, for example, −(−8) = 8.
If you're trying to talk about modular arithmetic with a modulus of 0, that would be nonsense. All numbers = to, say m < n mod(n), have the same remainder m when divided by n. Since mod(0) would thus require division by 0, which is undefined, mod(0) would also be undefined.
1 mod 1 = 0 (as mod 1 is always 0)
Just subtract 1 and add 1 afterwards.
In most programming languages, you need to watch out when finding a "previous" value, because for negative numbers, modulo does not work as you want in this case: it returns a negative number.
Here's the C/C++ version:
int next(int i, int m, int n) { return (i + m - 1) % n + 1; } int prev(int i, int m, int n) { return (i - m + n - 1) % n + 1; }
However, in Perl modulo always returns a positive value (at least when the second operand is a positive integer). Basically it does what you want. So you can write the following and leave out the + $_[2]
:
sub nxt { ($_[0] + $_[1] - 1) % $_[2] + 1; } sub prv { ($_[0] - $_[1] - 1) % $_[2] + 1; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With