Turn random number problem

Source: Internet
Author: User
Tags shuffle

Random number ProblemCategory: Programming Pearls Data Structure & algorithm offer on the the-the-2013-08-21 -22:51 775 people read reviews (1) favorites report

Directory (?) [+]

Initial problem: Randomly select m number (0<=m<=n) from n number.

For the sake of description, the problem can be abstracted as: the number of M is randomly selected from the N number of 0-n-1. The random numbers that the computer can provide are pseudo-random, and we assume that the pseudo-random numbers provided by the computer are really random.

Original articles, reproduced please specify the source: http://blog.csdn.net/fastsort/article/details/10162871

0. Generate a random number

The RAND function provided by the system (C + +) is only 15 bits, and if it does not meet the requirements, it needs to expand itself, and the 30-bit random function is as follows:

[CPP]View Plaincopyprint?
  1. /** @brief Returns a random number of 30bit
  2. * * @note system comes with Rand only 15bit
  3. */
  4. int Bigrand ()
  5. {
  6. static bool flag=false;
  7. if (flag==false)
  8. {
  9. Srand (Time (0));
  10. Flag = true;
  11. }
  12. return (rand () <<15) +rand ();
  13. }


1. The simplest solution

Each time a random number between 0-n-1 is generated, it is placed in a collection until the size of the collection is M. C + + STL has set, more convenient:

[CPP]View Plaincopyprint?
  1. void Getrandnum_set (int m,int n)
  2. {
  3. cout<<__function__<<":";
  4. set<int> S;
  5. While (signed (S.size ()) <m)
  6. {
  7. S.insert (Randint (0,n-1));
  8. }
  9. set<int>::iterator i=s.begin ();
  10. While (I!=s.end ())
  11. cout<<*i++<<"";
  12. cout<<endl;
  13. }
The above code works fine, but when M approaches N and is large, the last few numbers will be difficult to produce. Because a large number of duplicates are generated.

How do you not produce duplicate numbers?

2, up to n times solution

Assuming that the current number of m remains to be selected,

Starting from 0 to n-1 this n number, with the probability of m/n selected 0: Total n number, to select m;

For 1: If 0 is selected, the probability of (m-1)/(n-1) Selection 1 (a total of n-1, to choose m-1); if unchecked, the probability of m/(n-1) is selected (a total of n-1, to choose m);

......

For I: A total of n-i, but also to choose M, then the probability of the selection is m/(n-i).

If you do not select one, the remaining number to be selected will be reduced by one.

So the code looks like this:

[CPP]View Plaincopyprint?
  1. /** @brief randomly selects m different numbers in [0-n]
  2. * * and output by order
  3. */
  4. void getrandnumsorted (int m,int n)
  5. {
  6. cout<<__function__<<":";
  7. if (m<0 | | m>=n) return;
  8. For (int i=0; m!=0 && i<n; i++)
  9. {
  10. if (Bigrand ()% (n-i) <m)
  11. {
  12. cout<<i<<"";
  13. m--;
  14. }
  15. }
  16. cout<<endl;
  17. }
Obviously, this time the output is selected from small to large order.

Where: The probability of If (Bigrand ()% (n-i) <m) is: m/(n-i).
Can be analyzed, the probability of each number selected is m/n:

Number of selected probabilities

0:m/n

1:m/n * (m-1)/(n-1) + (1-m/n) * m/(n-1) =m/n;

2: A lot of things added, here will not write ...

......

3, non-sequential output

There are two workarounds if there is a requirement for non-sequential output.

One is to save the above results and then scramble the saved array.

There is also a direct generation of M random numbers.

First of all, the direct production of M random numbers, in fact, is the first one randomly selected from the 0-n-1, and then the number of the remaining n-1 randomly selected as the second one ... Until the election of the first M. This is called "perfect shuffle" or scrambled arrays.

[CPP]View Plaincopyprint?
  1. /** @brief randomly selects m different numbers in [0-n]
  2. * * and random output
  3. */
  4. void Getrandnum (int m, int n)
  5. {
  6. cout<<__function__<<":";
  7. int * p= (int*) malloc (sizeof (int) *n);   //!!!
  8. For (int i=0;i<n;i++)
  9. P[i] = i;
  10. ///shuffle P[0...m-1]
  11. For (int i=0; i<m; i++)
  12. {
  13. Swap (P[i],p[randint (i,n-1)));
  14. cout<<p[i]<<"";
  15. }
  16. cout<<endl;
  17. Free (p);
  18. }

A function is required to randomly generate a certain range of numbers:

[CPP]View Plaincopyprint?
    1. /** @brief Returns a random number between [L,u] **/
    2. int randint (int L, int u)
    3. {
    4. L = l<u?l:u;
    5. U = l<u?u:l;
    6. return Bigrand ()% (u-l+1) + L;
    7. }

The problem with this algorithm is that if n is large, m is small and the waste to the auxiliary space is too severe. Because it opens up so much space, the substance only uses a very small part.

The other is to first order the number of M-random, and then upset:

[CPP]View Plaincopyprint?
  1. /** @brief randomly selects m different numbers in [0-n]
  2. * * and random output
  3. */
  4. void GetRandNum2 (int m, int n)
  5. {
  6. cout<<__function__<<":";
  7. int * p= (int*) malloc (sizeof (int) *m);
  8. int tm=m;
  9. For (int i=0,j=0; m!=0 && i<n; i++)
  10. {
  11. if (Bigrand ()% (n-i) <m)
  12. {
  13. P[j++]=i;  //cout<<i<< "";
  14. m--;
  15. }
  16. }
  17. For (int i=0; i<TM; i++)
  18. {
  19. Swap (P[i],p[randint (i,tm-1)]);
  20. cout<<p[i]<<"";
  21. }
  22. cout<<endl;
  23. Free (p);
  24. }

4. Randomly read a line in a file

Randomly reads a row in a file without knowing the total number of rows in the file.

The most intuitive way to do this is to read the file first, and determine the total number of rows N. It then generates a random number m of 1-n and then reads the second row. Obviously this is possible, but the problem is that if the file is large, you have to traverse the file 1.5 times on average. Efficiency is low.

And if the file does not grow, then this method will not work.

Inspired by the algorithm above, it can actually be read only once.

First read the first line, if there is only one row, it is finished, set to lines;

If there is a 2nd line, replace line with a probability of 1/2, at which point the probability of 1 or 22 rows being selected is the same.

If there is a 3rd line, then the probability of 1/3 is the line; the probability of the 3rd row being selected is 1/3,1, and the probability of 22 rows being selected is 1/2*2/3=1/3.

......

Line I, replace lines with the probability of 1/i.

Until the end of the file.

[CPP]View Plaincopyprint?
  1. /** @brief randomly read a line from the file fname */
  2. void Getonelinerand (const char *fname)
  3. {
  4. cout<<__function__<<":";
  5. String Line,str_save;
  6. Ifstream ins (fname);
  7. int cnt=1;
  8. While (Getline (ins,line))
  9. {
  10. if (cnt==1)
  11. {
  12. Str_save = line;
  13. }
  14. Else
  15. {
  16. if (Randint (1,cnt) ==1)///[1,cnt]
  17. Str_save = line;
  18. }
  19. cout<<cnt<<":" <<line<<endl;
  20. cnt++;
  21. }
  22. cout<<"Rand line:" <<str_save<<endl;
  23. Ins.close ();
  24. }
here if (Randint (1,cnt) ==1) in 1, can be any one of the values in [1,cnt], the probability is 1/cnt.

5, Random Read K line

Read the K line first, save in an array (assuming that the file has at least k rows);

Then, each row is read with the probability of k/n replacing any row in the array, where n is the number of rows currently read in total.

[CPP]View Plaincopyprint?
  1. /** @brief randomly read K lines from File fname
  2. */
  3. void Getrandlines (const char *fname, int k)
  4. {
  5. cout<<__function__<<":";
  6. String * kstr = new string[k], line;
  7. Ifstream ins (fname);
  8. int cnt=1;
  9. While (cnt<=k)///read the first k line first
  10. {
  11. if (getline (ins,kstr[cnt-1))) cnt++;
  12. else break ; File does not have K line, exit directly
  13. }
  14. While (Getline (ins,line))
  15. {
  16. if (Randint (1,cnt) <=k) / //p=k/cnt
  17. {
  18. Swap (Kstr[randint (1,k) -1],line); /// randomly replace one row
  19. }
  20. cnt++;
  21. }
  22. For (int i=0; i<k; i++)
  23. {
  24. cout<<kstr[i]<<endl;
  25. }
  26. cout<<endl;
  27. delete[] KSTR;
  28. Ins.close ();
  29. }


Please refer to "Programming Zhu Ji Nanxiong-12th chapter" for other questions.

Original articles, reproduced please specify the source: http://blog.csdn.net/fastsort/article/details/10162871

Turn random number problem

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.