BeguiledFoil

So in C# when I do -1%something I get -1, which means I can't really use it as an array index without a bunch of stupid error checking.  Is there some way to force the modulo operator to actually give me numbers from my field (e.g 0-5 for modulo 6)

Edit: Well, I made this post at 2:00 am and it shows, here is what I have issue with:

i = (i+1) % 6 will result in numbers from 0 to 5, which I could use for an array index

i = (i-1) % 6 will result in numbers from 0 to -5, which can't be used in an array index

Obviously, the absolute value of those results would not conform to any logical value, either (for instance, array[-1] and array[1] would be the same value, even though they should be 2 values apart if I decremented twice from 1 to get to -1).

What I want is a more traditional (in my mind) modulo operator, which gives me only positive remainders.  Obviously I can work around this myself with some conditionals, but I'm looking for an elegant and maintainable solution...



Re: XNA Game Studio Express C# modulus operator % sucks?

Arek Bal

I can't really understand what you are trying to achieve...(bad description ).
Maybe try some fun with types and casting.
It's an example for cutting out float to uint:
string String()
{
float yourFloat = 0.13f;
uint i = 0;
if((yourFloat > uint.MinValue) && (yourFloat < uint.MaxValue))
{
    i = (uint)yourFloat;
}
else
{
    if(yourFloat < uint.MinValue)
        i = uint.MinValue;
    if(yourFloat > uint.MaxValue)
        i = uint.MaxValue;

return i.ToString();
}

or that one to change signs

uint i;
int m = -99;
if(m < uint.MinValue)
{
    i = (uint)(m - (2 * m));
}
return i.ToString();

EDIT:
IMO modulo operator was designed that way to allow you perform some special calculations on smaller  than 0 modulo results(more flexibility of operator). It's up to you how nice you gonna change negative result to positive. Modulo was always "slow" operator. This one more operation will not create any real performance problem.




Re: XNA Game Studio Express C# modulus operator % sucks?

Kyle0654

That's the definition of modulo - it doesn't suck. Modulo represents the remainder after division. In the case of negative numerators, you'll end up with a negative remainder.

You could just subtract from your maximum value if the remainder turns up negative. i.e.

if (nval < 0) nval += maxval;

it's not perfect, but it would work. You could also just always add the maximum value after doing a modulo operation and then do one more modulo operation - then you'd skip the conditional. Either way it shouldn't kill performance too bad.

nval = (curval < 0) (curval % maxval) + maxval : curval % maxval;






Re: XNA Game Studio Express C# modulus operator % sucks?

BeguiledFoil

That's definitely one definition of modulo, but there are other... interpretations: http://www.google.com/search client=opera&rls=en&q=-3+%25+6&sourceid=opera&ie=utf-8&oe=utf-8

At any rate, the operator woud be far more useful if it could be used to directly specify a ring. For instance, if I want to ensure that a result is within the range of my index, I would much prefer to be able to simply take the answer % my array count rather than handling negative answers separately.





Re: XNA Game Studio Express C# modulus operator % sucks?

BeguiledFoil

Modulo was always "slow" operator. This one more operation will not create any real performance problem.

How is modulo a slow operator I recall seeing some very fast ways of performing it in assembly or directly at the hardware level...





Re: XNA Game Studio Express C# modulus operator % sucks?

Arek Bal

I should write "Modulo was always slower then other standard operators".




Re: XNA Game Studio Express C# modulus operator % sucks?

Stephen Styrchak - MSFT

BeguiledFoil wrote:

i = (i+1) % 6 will result in numbers from 0 to 5, which I could use for an array index

i = (i-1) % 6 will result in numbers from 0 to -5, which can't be used in an array index

You want to decrement i and keep it within range of your array. This is certainly achievable, but you need to apply a little more mathematics.

Here's how you do it:

i = (i + 5) % 6;

Rewritten in a more general way,

i = (i + (a.Length - 1)) % a.Length;

Which is equivalent to this:

i = ((i + a.Length) - 1) % a.Length;

This assumes that i is within the range [0, a.Length-1] to begin with, and a is the array you want to access.

--Stephen





Re: XNA Game Studio Express C# modulus operator % sucks?

ImagineNation

Hi Steven;

You made a slight error ...

using your code, if I =-1, then i=(i+5) %6 = 4 which is wrong.

In fact the answer is i=(i+6) % 6 which gives 5. (obviously, the next value after 0 s/be 5)

And to generalise i=(i+a.length) % a.length


BeguiledFoil -- to keep it simple, just to (i=i+6) mod 6 and that will work for postive AND negative numbers.

Of course, if you have HUGE negative numbers (IE -597 or whtaver) then just add a bigger adjustment, for exaqmple 600 or 6000 or 60000 will all work -- basically all you are doign is shifting the number into the positive side of the modulus. You aren,'t changing the number at all because 600 or 6000 or 60000 % 6 all equal zer0 --- in other words, you added zero to your number!

A nice mathematical trick.

Jamie







Re: XNA Game Studio Express C# modulus operator % sucks?

ImagineNation

BeguiledFoil -- to keep it simple, just to (i=i+6) mod 6 and that will work for postive AND negative numbers.

Of course, if you have HUGE negative numbers (IE -597 or whtaver) then just add a bigger adjustment, for example 600 or 6000 or 60000 will all work -- basically all you are doing is shifting the number into the positive side of the modulus. You aren't changing the number at all because 600 or 6000 or 60000 % 6 all equal zer0 --- in other words, as far as modulus is concerned, you added zero to your number!

A nice mathematical trick.

Jamie




Re: XNA Game Studio Express C# modulus operator % sucks?

Shawn Hargreaves - MSFT

If you don't want negative values, just make your value an unsigned int rather than a regular int. If you're converting from a signed type that you can't change, just cast that to unsigned int before you take the modulus.





Re: XNA Game Studio Express C# modulus operator % sucks?

Stephen Styrchak - MSFT

ImagineNation wrote:
Hi Steven;

You made a slight error ...

using your code, if I =-1, then i=(i+5) %6 = 4 which is wrong.

In fact the answer is i=(i+6) % 6 which gives 5. (obviously, the next value after 0 s/be 5)

And to generalise i=(i+a.length) % a.length

Nope, I said that this assumed that i was within the range [0, a.Length-1] to begin with. As in, you have a valid array index, and you want to compute the next array index in a descending order. For example, 5, 4, 3, 2, 1, 0, then back to 5, ...

I was solving the original problem correctly, not correcting the problem with the original solution.

Since we're talking about a range of 0 to 5, I can easily just show you that it's right for all values of i. I'll start with i == 0, and each time the statement will provide the next index in the sequence.

(0 + 5) % 6 == 5

(5 + 5) % 6 == 4

(4 + 5) % 6 == 3

(3 + 5) % 6 == 2

(2 + 5) % 6 == 1

(1 + 5) % 6 == 0

QED.

What you wrote, i = (i + 6) % 6, does nothing at all if i is already within the range specified. You seem to be trying to correct the negative value (by finding the smallest positive value congruent to i modulo 6), but I was suggesting a way to never compute a negative value in the first place.

--Stephen





Re: XNA Game Studio Express C# modulus operator % sucks?

Stephen Styrchak - MSFT

ImagineNation wrote:
Of course, if you have HUGE negative numbers (IE -597 or whtaver) then just add a bigger adjustment, for example 600 or 6000 or 60000 will all work -- basically all you are doing is shifting the number into the positive side of the modulus. You aren't changing the number at all because 600 or 6000 or 60000 % 6 all equal zer0 --- in other words, as far as modulus is concerned, you added zero to your number!

What you're describing is, "How do I find the smallest positive integer congruent to i modulo m "

To solve this problem, you do not need to know the magnitude of the value i. If you try to guess and add a big number, you may overflow and end up with a negative number, which would be undesireable.

The answer to this problem is:

i = ((i % m) + m) % m; // for any integer i, and any integer m where m > 0 and m <= Int32.MaxValue / 2.

I don't think this is what the original poster was asking about, though.

--Stephen





Re: XNA Game Studio Express C# modulus operator % sucks?

XPM

Depending on what else you're trying to accomplish, what about using a different type of array that "accepts negative indices," such as a Hashtable