modulus and array.length
Steven Schveighoffer
schveiguy at yahoo.com
Tue Nov 16 10:19:36 PST 2010
On Tue, 16 Nov 2010 10:55:24 -0500, David Osborne <krendilboove at gmail.com>
wrote:
> Hi,
>
> I've noticed that the modulus operator acts differently when the divisor
> is
> the length of an array and the dividend is negative.
> For instance, this code:
>
> import std.stdio;
> const int x = 4;
> void main(){
> int[x] arr = [0, 1, 2, 3];
>
> writeln("Using arr.length");
> for(int i = -3; i <= 0; i++){
> writefln("%d mod %d = %d", i, arr.length, i % arr.length);
> }
> writeln("Using x");
> for(int i = -3; i <= 0; i++){
> writefln("%d mod %d = %d", i, x, i % x);
> }
> }
>
> Produces this output:
>
> Using arr.length
> -3 mod 4 = 1
> -2 mod 4 = 2
> -1 mod 4 = 3
> 0 mod 4 = 0
> Using x
> -3 mod 4 = -3
> -2 mod 4 = -2
> -1 mod 4 = -1
> 0 mod 4 = 0
>
> Which is a useful (but undocumented?) feature that lets you loop through
> arrays backwards.
> However, when the length of the array is odd...
> const int x = 3;
> ...
> int[x] arr = [0, 1, 2];
> It looks like this:
>
> Using arr.length
> -3 mod 3 = 1 <-- this should be 0
> -2 mod 3 = 2 <-- this should be 1
> -1 mod 3 = 0 <-- this should be 2
> 0 mod 3 = 0
> Using x
> -3 mod 3 = 0
> -2 mod 3 = -2
> -1 mod 3 = -1
> 0 mod 3 = 0
>
> Does anyone know of a reason for this? It doesn't seem like a bug, but I
> don't know why it would do something like that.
>
> Upon further investigation, I found that when arr.length is even, i acts
> like (x*(abs(i)/x + 1) + i) , and when arr.length is odd, i acts like
> (x*(abs(i)/x - 1) + i)
>
> (I'm using dmd 2.049 on linux)
Simple, array.length is an unsigned value, so the signed operands are
promoted to unsigned through normal integer promotion:
cast(uint)-3 -> 4_294_967_293u
4_294_967_293u % 3u -> 1
I don't think this "undocumented" feature is valid. In fact, it may not
be valid for evens as well that aren't powers of 2.
-Steve
More information about the Digitalmars-d
mailing list