C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old October 16th, 2011, 03:10 AM
leszek31417 leszek31417 is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2011
Posts: 313 leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 56 m
Reputation Power: 0
Generating distinct random numbers

From time to time, I need an array of distinct, randomly chosen, positive integers.

One solution is below:

Code:
   int a[N];

   for ( i=0; i<N; i++ ) a[i] = i;

   for ( t=0; t<9999; t++ ) {
      i = rand()%N;
      j = rand()%N;
      help = a[i]; a[i] = a[j]; a[j] = help; // swap a[i] with a[j]
   }


Do you know something better ?


Reply With Quote
  #2  
Old October 16th, 2011, 05:08 AM
LittleGrin LittleGrin is offline
Contributing User
Dev Shed Novice (500 - 999 posts)
 
Join Date: Oct 2007
Posts: 921 LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Week 11 h 50 m 18 sec
Reputation Power: 535
You don't need the second loop to go 9999 times. N times is enough. Only one random value per loop iteration is also enough.

For the shuffling, I'd probably use the technique which is (IIRC) employed in the C++ random_shuffle() algorithm.

Code:
    for (size_t i = 0; i < N; ++i) a[i] = i;
    for (size_t i = N-1; i > 0; --i)
    {
         size_t i_rand = rand() % N
         int help = a[i];
         a[i] = a[i_rand];
         a[i_rand] = help;
    }
__________________
Right 98% of the time, and don't care about the other 3%.

“It has been said that the great scientific disciplines are examples of giants standing on the shoulders of other giants. It has also been said that the software industry is an example of midgets standing on the toes of other midgets.” (Alan Cooper)

Reply With Quote
  #3  
Old October 16th, 2011, 07:18 AM
leszek31417 leszek31417 is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2011
Posts: 313 leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 56 m
Reputation Power: 0
I see !...

Swapping a[i] with random a[j].

That's better ...

Why backward loop ?

And (most important) why only N steps ?

...

Thank you!

Reply With Quote
  #4  
Old October 16th, 2011, 07:59 PM
b49P23TIvg's Avatar
b49P23TIvg b49P23TIvg is online now
Contributing User
Dev Shed Loyal (3000 - 3499 posts)
 
Join Date: Aug 2011
Posts: 3,458 b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level) 
Time spent in forums: 1 Month 2 Weeks 4 Days 6 h 33 m 33 sec
Reputation Power: 403
gsl shuffle

gsl shuffle

The gsl random routines let you select from a good variety of prngs using the environment.


And why only one pass through the loop? Each number is given a chance to move to a different location.
SWAP(a[i -- known] , a[j---random] )
I also don't understand the "backward through the loop" business.

Without running it with print statements, it looks like a[0] is neglected.

Code:
    for (size_t i = 0; i < N; ++i) a[i] = i;
    for (size_t i = N; i-- > 0; )  /* this looks correct to me */
    {
         size_t i_rand = rand() % N
         int help = a[i];
         a[i] = a[i_rand];
         a[i_rand] = help;
    }


Also, and this is probably too much work, if all the bits of from the prng are good, and you need a small random integer, you can use R%N as your random number, and then take R/=N while R>N . I treat my random numbers as precious.

Last edited by b49P23TIvg : October 16th, 2011 at 08:03 PM. Reason: clarify

Reply With Quote
  #5  
Old October 17th, 2011, 02:38 AM
leszek31417 leszek31417 is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2011
Posts: 313 leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 56 m
Reputation Power: 0
Maybe like this :

Code:
   for ( i=0; i<N; i++ ) a[i] = i;

   for( i=N-1; i>0; i-- ){
 
      j = rand()%(i+1); // 0 <= j <= i
 
      h = a[i]; a[i] = a[j]; a[j] = h;  // swap a[i] with a[j]

   }


This explains counting down.
And there is no need for last step (when i=0).

...

Thank you for all remarks !

Reply With Quote
  #6  
Old October 17th, 2011, 03:41 AM
LittleGrin LittleGrin is offline
Contributing User
Dev Shed Novice (500 - 999 posts)
 
Join Date: Oct 2007
Posts: 921 LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level)LittleGrin User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Week 11 h 50 m 18 sec
Reputation Power: 535
I just looked up the algorithm. I got it wrong - I was typing it in from memory, after all. The line
Code:
    size_t i_rand = rand() % N

should be
Code:
    size_t i_rand = rand() % (i + 1);

(I've added a missing semi-colon too). This is consistent with leszek's last post.

If you want a mathematical discussion of the reasoning, dig out Donald Knuth's "The Art of Computer Programming" - specifically the second volume entitled "Seminumerical Algorithms". It is discussed in Section 3.4.2 "Random Sampling and Shuffling" as "Algorithm P".

The results are uniformly distributed (i.e. all shuffled arrays are equally likely). If you really want to dig into the reasoning, Knuth gives references to the articles where the algorithm was first published.

When tweaking algorithms like this it is very easy to produce something that looks like a random shuffle but really is not. Iterating a few more times, for example, would change the distribution of results.

Reply With Quote
  #7  
Old October 17th, 2011, 04:00 AM
leszek31417 leszek31417 is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2011
Posts: 313 leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level)leszek31417 User rank is Corporal (100 - 500 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 56 m
Reputation Power: 0
Now, the algorithm models exactly the experiment of
selecting balls from an urn without replacement.

Thank you.

Reply With Quote
  #8  
Old October 17th, 2011, 05:28 AM
mitakeet's Avatar
mitakeet mitakeet is offline
I'm Baaaaaaack!
Dev Shed God 1st Plane (5500 - 5999 posts)
 
Join Date: Jul 2003
Location: Maryland
Posts: 5,538 mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level)mitakeet User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 2 Weeks 4 Days 2 h 38 m 46 sec
Reputation Power: 242
In my early days as a programmer I needed to do exactly this. I experimented with lots of ways to get it, but the swapping locations in an initially sorted array was the fastest and most reliable way I found.
__________________

My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
Free code: http://sol-biotech.com/code/.
Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
--Me, I just made it up

The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
--George Bernard Shaw

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > Generating distinct random numbers

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap