Strange behavior of modulo in array index

G

Guest

I have a loop which iterates over an array in a particular order:

for (j = 0; j < 16; j++) T[(4 - j) % 4] = ...;

The loop proceeds normally for j = 0 through j = 4, but gives an
IndexOutOfRangeException at j = 5. Playing with the watch window seems to
indicate that the modulo is being completely ignored:

j = 0x5 (int)
T[(4 - j) % 4] = error: index '4-j%4' out of bound for pointer/array 'T'
(4 - j) % 4 = 0xffffffff (int)
4 - j = 0xffffffff (int)
0xffffffff % 4 = 0x3 (long)

I'm stumped. Any ideas?
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Hi Ben,

-1 % 4 = -1 that is the correct result (0*4 - 1).
Unless T is collection that you have written by yourself and it supposrts
negative indices or dictionalry any other .NET collection or array will
throw that exception
 
J

Jon Skeet [C# MVP]

Ben Blank said:
I have a loop which iterates over an array in a particular order:

for (j = 0; j < 16; j++) T[(4 - j) % 4] = ...;

The loop proceeds normally for j = 0 through j = 4, but gives an
IndexOutOfRangeException at j = 5. Playing with the watch window seems to
indicate that the modulo is being completely ignored:

j = 0x5 (int)
T[(4 - j) % 4] = error: index '4-j%4' out of bound for pointer/array 'T'
(4 - j) % 4 = 0xffffffff (int)
4 - j = 0xffffffff (int)
0xffffffff % 4 = 0x3 (long)

I'm stumped. Any ideas?

It's not being ignored at all. The range for x % y is (-y, y) (note
exclusivity of bounds).

Note that it's the remainder operator, not the modulo operator, which
is why there's the difference. (There's no modulo operator.)
 
G

Guest

Stoitcho Goutsev (100) said:
-1 % 4 = -1 that is the correct result (0*4 - 1).

Odd. I was under the impression that modulo N would always return a
positive result in the range of 0 .. N-1. I'll have to play around with
changing j to an unsigned integer instead. Thanks for your quick response.
 
G

Guest

Jon Skeet said:
It's not being ignored at all. The range for x % y is (-y, y) (note
exclusivity of bounds).

Note that it's the remainder operator, not the modulo operator, which
is why there's the difference. (There's no modulo operator.)

Ah! And that would be the thinko which caused this; thanks for pointing it
out. For the record (and anyone else making the same mistake I did),
changing j to an unsigned integer caused the expression to behave as I
expected it to.
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Jon,

Actually this is exactly modulo operation according to the latest definition

"According to the newer convention, in general, a mod n is the remainder on
integer division of a by n. Depending on the implementation, the remainder r
is typically constrained to 0 < |r| < |n|, with a negative remainder only
resulting when n < 0."

--

Stoitcho Goutsev (100) [C# MVP]


Jon Skeet said:
Ben Blank said:
I have a loop which iterates over an array in a particular order:

for (j = 0; j < 16; j++) T[(4 - j) % 4] = ...;

The loop proceeds normally for j = 0 through j = 4, but gives an
IndexOutOfRangeException at j = 5. Playing with the watch window seems
to
indicate that the modulo is being completely ignored:

j = 0x5 (int)
T[(4 - j) % 4] = error: index '4-j%4' out of bound for pointer/array 'T'
(4 - j) % 4 = 0xffffffff (int)
4 - j = 0xffffffff (int)
0xffffffff % 4 = 0x3 (long)

I'm stumped. Any ideas?

It's not being ignored at all. The range for x % y is (-y, y) (note
exclusivity of bounds).

Note that it's the remainder operator, not the modulo operator, which
is why there's the difference. (There's no modulo operator.)
 
J

Jon Skeet [C# MVP]

Stoitcho Goutsev (100) said:
Actually this is exactly modulo operation according to the latest definition

"According to the newer convention, in general, a mod n is the remainder on
integer division of a by n. Depending on the implementation, the remainder r
is typically constrained to 0 < |r| < |n|, with a negative remainder only
resulting when n < 0."

Well, that "typically" certainly isn't the case here (-1 % 2 == -1).

I dare say it depends on what definition you end up using, but it looks
like the OP would expect modulo to give a positive value but
understands that a remainder can be negative.
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Jon,
Well, that "typically" certainly isn't the case here (-1 % 2 == -1).

n % x = r
-1 % 2 = -1
this is exactly the case

r is negative because n is negative
I dare say it depends on what definition you end up using, but it looks
like the OP would expect modulo to give a positive value but
understands that a remainder can be negative.

Well, I'd expect the result to be positive if the operation was defined only
for positive numbers. In the case it is defined for negative as well I'd
expect negative result
 
J

Jon Skeet [C# MVP]

Stoitcho Goutsev (100) said:
n % x = r

No, a % n = r, using the terminology above.
-1 % 2 = -1
this is exactly the case

r is negative because n is negative

No it's not - n here is 2, it's a which is -1. Your definition is
talking about situations like 13 % -5.
Well, I'd expect the result to be positive if the operation was defined only
for positive numbers. In the case it is defined for negative as well I'd
expect negative result

Well, not by the definition you were using above, unless n is negative.
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Well actually now I'm confused. Frankly, I haven't noticed that actually the
definition talks about a % n = r.

If it is the reminder of the integer devision I would say that 13 % -3 = -4
and reminder 1 it looks like the definition has an error it should be that
r < 0 when a < 0
 
J

Jon Skeet [C# MVP]

Stoitcho Goutsev (100) said:
Well actually now I'm confused. Frankly, I haven't noticed that actually the
definition talks about a % n = r.

If it is the reminder of the integer devision I would say that 13 % -3 = -4
and reminder 1 it looks like the definition has an error it should be that
r < 0 when a < 0

Maybe. It's definitely a matter of definition though - and fortunately,
the C# spec does specify what the results of '%' should be, nice and
clearly :)
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Maybe. It's definitely a matter of definition though - and fortunately,
the C# spec does specify what the results of '%' should be, nice and
clearly :)

Well, C# specs correctly call % operator 'reminder operator', but "C#
Programmer Reference" which can be found in MSDN call this operator "modulus
operator". Probably this is where the confusion comes from. Mathematicians
probably will find the information in MSDN ambiguous :)

Anyways, everything's clear now
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top