Array.Sort exception when randomizing an Array

P

Paul van Brenk

When you run the Shuffle[0] method often enough it will throw exception[1].
And I can't figure out why.

Anybody?

Paul van Brenk

[0] the code:
static void Shuffle(){
int[] ints = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
System.Random rand = new System.Random((int)DateTime.Now.Ticks);
Array.Sort(ints, delegate(int x, int y){
// since you're not allowed to return anything else than 0 for
x.CompareTo(x)
if (x == y) {
return 0;
}
return rand.Next(-1,2);
}
);
}

[1] the exception:
exc.Message "IComparer (or the IComparable methods it relies upon) did not
return zero when Array.Sort called x. CompareTo(x). x: '5' x's type:
'Int32' The IComparer: 'System.Array+FunctorComparer`1[System.Int32]'."
 
C

Christoph Nahr

When you run the Shuffle[0] method often enough it will throw exception[1].
And I can't figure out why.

Neither can I, but I don't get the exception either. How often is
"often enough?" I ran your method ca. 100,000 times with no luck.
 
P

Paul van Brenk

mmh, interesting... I get the exception under 200 iterations. I'll try it on
a different machine tomorrow.

thanks anyway,

Paul

Christoph Nahr said:
When you run the Shuffle[0] method often enough it will throw
exception[1].
And I can't figure out why.

Neither can I, but I don't get the exception either. How often is
"often enough?" I ran your method ca. 100,000 times with no luck.
 
?

=?iso-8859-1?Q?Anders=20Nor=e5s?=

When you run the Shuffle[0] method often enough it will throw
exception[1]. And I can't figure out why.
Yes. Since you're making a random decision on wheter int x should be sorted
before or after int y you'll get an exception whenever you reach the last
element in the array and your delegate returns something different from 0.
This doesn't happen every time you call the Shuffle method, and it is less
likely to happen the faster your computer is because the random generator
relies on the system clock to generate "random" number. If you place a Thread.Sleep(1)
within the loop calling your Shuffle method you'll slow the processing down,
and you'll be more likely to get an exception.

The way you're sorting the array is not only error prone, it is also inefficient.
The sort delegate will be called more than ten times for each call to the
Shuffle method, since the method is randomized, the exact number cannot be
predicted, but a quick test I wrote had an average of 35 calls for 200 iterations.

A better way to get a randomize int array with the numbers between 1-10 is
shown below:
Random r=new Random();
int[] numbers=new int[10];
for (int i=0; i<10; i++)
{
numbers=r.Next(1,10);
}

Regards,
Anders Norås
http://dotnetjunkies.com/weblog/anoras/
 
P

Paul van Brenk

Anders Norås said:
When you run the Shuffle[0] method often enough it will throw
exception[1]. And I can't figure out why.
Yes. Since you're making a random decision on wheter int x should be
sorted before or after int y you'll get an exception whenever you reach
the last element in the array and your delegate returns something
different from 0.

You sure? If I shortcircuit the array with "return 1;" everything works as
expected.
This doesn't happen every time you call the Shuffle method, and it is less
likely to happen the faster your computer is because the random generator
relies on the system clock to generate "random" number. If you place a
Thread.Sleep(1) within the loop calling your Shuffle method you'll slow
the processing down, and you'll be more likely to get an exception.

The way you're sorting the array is not only error prone, it is also
inefficient. The sort delegate will be called more than ten times for each
call to the Shuffle method, since the method is randomized, the exact
number cannot be predicted, but a quick test I wrote had an average of 35
calls for 200 iterations.

A better way to get a randomize int array with the numbers between 1-10 is
shown below:
Random r=new Random();
int[] numbers=new int[10];
for (int i=0; i<10; i++)
{
numbers=r.Next(1,10);
}


this would give me an array of 10 random integeres not an array of integers
0-9 in random order.
 
?

=?iso-8859-1?Q?Anders=20Nor=e5s?=

A better way to get a randomize int array with the numbers between
1-10 is
shown below:
Random r=new Random();
int[] numbers=new int[10];
for (int i=0; i<10; i++)
{
numbers=r.Next(1,10);
}

this would give me an array of 10 random integeres not an array of
integers 0-9 in random order.


Ops. Sorry Paul, I cut and pasted the wrong code snippet. Below is the code
I intended to post.
List<int> numbers=new List<int>(new int[] { 1,2,3,4,5,6,7,8,9,10 });
List<int> randomizedNumbers=new List<int>();
Random r=new Random();
while (numbers.Count>0)
{
int i=r.Next(0,numbers.Count);
randomizedNumbers.Add(numbers);
numbers.RemoveAt(i);
}

Regards,
Anders Norås
http://dotnetjunkies.com/weblog/anoras/
 
P

Paul van Brenk

thanks,

I used this method from the powercollections, which is a little more
generic:

public static T[] RandomShuffle<T>(IEnumerable<T> collection, Random
randomGenerator)

{

// We have to copy all items anyway, and there isn't a way to produce the
items

// on the fly that is linear. So copying to an array and shuffling it is an
efficient as we can get.

if (collection == null)

throw new ArgumentNullException("collection");

if (randomGenerator == null)

throw new ArgumentNullException("randomGenerator");

T[] array = Algorithms.ToArray(collection);

int count = array.Length;

for (int i = count - 1; i >= 1; --i) {

// Pick an random number 0 through i inclusive.

int j = randomGenerator.Next(i + 1);

// Swap array and array[j]

T temp = array;

array = array[j];

array[j] = temp;

}

return array;

}



Anders Norås said:
A better way to get a randomize int array with the numbers between
1-10 is
shown below:
Random r=new Random();
int[] numbers=new int[10];
for (int i=0; i<10; i++)
{
numbers=r.Next(1,10);
}

this would give me an array of 10 random integeres not an array of
integers 0-9 in random order.


Ops. Sorry Paul, I cut and pasted the wrong code snippet. Below is the
code I intended to post.
List<int> numbers=new List<int>(new int[] { 1,2,3,4,5,6,7,8,9,10 });
List<int> randomizedNumbers=new List<int>();
Random r=new Random();
while (numbers.Count>0)
{
int i=r.Next(0,numbers.Count);
randomizedNumbers.Add(numbers);
numbers.RemoveAt(i);
}

Regards,
Anders Norås
http://dotnetjunkies.com/weblog/anoras/
 

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