4

So I've got this thing where I got the following operation:

NSInteger articleIndex = self.featuredArticlesCounter % self.featuredArticles.count;

In this case self.featuredArticlesCounter is -1 and
self.featuredArticles.count is 10

So it's basically -1 % 10, which should be 9, but the result is 5 instead.

Google says it's 9.

And if I do NSInteger articleIndex = -1 % 10; it gives me -1

I've tried casting the NSUInteger from count to NSInteger and that doesn't work. I've tried inserting brackets all over the place but that didn't work either.

I've since switched to using ((-1 % 10) + 10) % 10.

But I'm still wondering what the deal is here. Any ideas?

Edit:

featuredArticlesCounter is a signed int

self.featuredArticles.count is an unsigned int

ughoavgfhw
  • 39,734
  • 6
  • 101
  • 123
Andrew
  • 3,166
  • 21
  • 32

2 Answers2

6

featuredArticlesCounter is evidently an unsigned int. When you thought you set it to -1, you really set it to 2**32 - 1 (~0). That number mod 10 is 5. (Apparently, 2**(8k)-1 % 10 is 5, so it doesn't matter what size unsigned it actually is)

As for why -1 % 10 is -1, I believe in C the mod of negative numbers is implementation-defined, but in this case (as in Java), it is defined such that x / y + x % y == x. If you plug negative numbers in, -1 / 10 + -1 % 10 = -1 -> -1 % 10 = -1.

Kevin
  • 53,822
  • 15
  • 101
  • 132
  • +1 for observation that all lengths of unsigned congruent to 5! – Nicholas Wilson Aug 30 '13 at 16:09
  • Unfortunately featuredArticlesCounter is a signed int, the other one is unsigned though, but I don't change its value. – Andrew Aug 30 '13 at 16:22
  • 2
    This is not true for all powers of 2. `(2^33 - 1)%10` is 1. It is true for 2^n iff n is a multiple of 4 > 0, which makes it equivalent to `(16^(n/4) - 1)%10`. The last digit of a power of 16 is always a 6, so after subtracting 1 the last digit is 5. – ughoavgfhw Aug 30 '13 at 17:28
  • 2
    @ugohoavgfhw: The comment says `all lengths of unsigned`, and it is intended to apply to modern systems where all integer types are multiples of 8-bit bytes, and the answer says `2**(8k)`, so it also applies only to multiple-of-eight powers of two. – Eric Postpischil Aug 30 '13 at 18:22
3

Perhaps the hardware (or software?) treats the number as an unsigned integer:

  1. -1 == 0xFFFFFFFF (in two's compliment encoding)

  2. 0xFFFFFFFF == 4294967295 (assuming the raw data is an unsigned integer)

  3. 4294967295 % 10 == 5 (trivial by observation of last digit)

This would be my best guess.

recursion.ninja
  • 5,377
  • 7
  • 46
  • 78