tags:

views:

123

answers:

4

What is a mathematical way of of saying 1 - 1 = 12 for a month calculation? Adding is easy, 12 + 1 % 12 = 1, but subtraction introduces 0, stuffing things up.

My actual requirement is x = x + d, where x must always be between 1 and 12 before and after the summing, and d any unsigned integer.

+3  A: 

Assuming x and y are both in the range 1-12:

((x - y + 11) % 12) + 1

To break this down:

// Range = [0, 22]
x - y + 11

// Range = [0, 11]
(x - y + 11) % 12

// Range = [1, 12]
((x - y + 11) % 12) + 1
Jon Skeet
What's the 'y'? x + 11 as a surrogate for 'x - 1', modulo 12.
Jonathan Leffler
x is in 1-12, y can be anything
ProfK
A: 

You have to be careful with addition, too, since (11 + 1) % 12 = 0. Try this:

x % 12 + 1

This comes from using a normalisation function:

norm(x) = ((x - 1) % 12) + 1

Substituting,

norm(x + 1) = (((x + 1) - 1) % 12 + 1

norm(x + 1) = (x) % 12 + 1
Greg Hewgill
+2  A: 

I'd work internally with a 0 based month (0-11), summing one for external consumption only (output, another calling method expecting 1-12, etc.), that way you can wrap around backwards just as easily as wrapping around forward.

>>> for i in range(15):
...  print '%d + 1 => %d' % (i, (i+1)%12)
...
0 + 1 => 1
1 + 1 => 2
2 + 1 => 3
3 + 1 => 4
4 + 1 => 5
5 + 1 => 6
6 + 1 => 7
7 + 1 => 8
8 + 1 => 9
9 + 1 => 10
10 + 1 => 11
11 + 1 => 0
12 + 1 => 1
13 + 1 => 2
14 + 1 => 3
>>> for i in range(15):
...  print '%d - 1 => %d' % (i, (i-1)%12)
...
0 - 1 => 11
1 - 1 => 0
2 - 1 => 1
3 - 1 => 2
4 - 1 => 3
5 - 1 => 4
6 - 1 => 5
7 - 1 => 6
8 - 1 => 7
9 - 1 => 8
10 - 1 => 9
11 - 1 => 10
12 - 1 => 11
13 - 1 => 0
14 - 1 => 1
Vinko Vrsalovic
I like this, it's the simplest and clearest.
ProfK
you might want to accept it then
Nathan Fellman
He did and later regretted it. It may have a problem in his platform. Would be nice to know though.
Vinko Vrsalovic
A: 

The % (modulus) operator produces an answer in the range 0..(N-1) for x % N. Given that your inputs are in the range 1..N (for N = 12), the general adding code for adding a positive number y months to current month x should be:

(x + y - 1) % 12 + 1

When y is 1, this reduces to

x % 12 + 1

Subtracting is basically the same. However, there are complications with the answers produced by different implementations of the modulus operator when either (or both) of the operands is negative. If the number to be subtracted is known to be in in the range 1..N, then you can use the fact that subtracting y modulo N is the same as adding (N - y) modulo N. If y is unconstrained (but positive), then use:

(x + (12 - (y % 12) - 1) % 12 + 1

This double-modulo operation is a common part of the solution to problems like this when the range of the values is not under control.

Jonathan Leffler