"Go" about C language generation of non-repeating random numbers

Source: Internet
Author: User
Tags decrypt goto rand

a random function, I am afraid that some people say this is the old growth talk ... Generally a lot of people have formed their own fixed format, because the use of random numbers is relatively large, when used more, take over the use of. But beginners don't do it, they always have doubts, I am a novice, and more than dishes ... In order to let the rookie like me see, I will try to say to let the experts dismiss (: because there may be too much content may be divided, we forgive ^

The advantage of the computer is that it is accurate, so it is not good at analog signals, but its drawbacks are the same. So the computer was in trouble on some analog issues ... For example, the random number, because the function, it is always determined that the algorithm will generate a definite result. The number of random numbers returned by various programming languages (literally pseudo-random numbers) is actually a set of values calculated from a recursive formula, and when the sequence is long enough, the set of values approximates to the uniform distribution. The standard library of C provides a random number generator RAND (defined in stdlib.h) that can return a pseudo-random integer evenly distributed between 0-rand_max (Rand_max is at least 32767, and generally defaults to 32767).

For example:

#include <stdio.h>
#include <stdlib.h>
void Main ()
{
for (int i=0;i<10;i+)
printf ("%d\n", Rand ());
}

If we are running for the first time and are not very clear about it, then it is basically a random sequence of equal probabilities between 0-rand_max. But if you run the second time you will find that the output is still the same as the first time. : (It turns out that rand () requires a seed (the initial value of the pseudo-random sequence) to generate the pseudo-random number, and if the seed is the same, the result of the same sequence (which is the benefit of the function t-t). This "advantage" is used by software to encrypt and decrypt. When encrypting, a pseudo-random sequence can be generated with a seed number, and the data is processed, and then the seed number is used to generate a pseudo-random sequence and restore the encrypted data. In this way, for those who do not know the number of seeds, it takes more than a few more things to decrypt. Of course, this exact same sequence is very bad for you. To solve this problem, you need to specify a different seed before each random sequence is generated, so that the computed random sequence will not be identical.

The Srand () is used to set the random number seed when rand () produces a random number. Before calling the rand () function to produce a random number, you must first use Srand () to set the random number seed (seed), and if the random number seed is not set, rand () will automatically set the random number seed to 1 when called (some say the default is 0, in confusion). The two examples above are that because no random number seed is set, each random number seed is automatically set to the same value of 1, which results in the same random values generated by rand (). (It may be known that the random function of the C language randomly, but the random function is not ANSI C standard, so that the random function can not be compiled under the GCC,VC compiler pass.) We can make up a ^0^ ourselves. We need to get the program to use a different seed every time, now the main problem is that the seed srand selection is not nearly random (there is no complete random), you can also artificially specify the number of seeds. Windows 9x/nt's game FreeCell allows the user to specify the number of seeds so that if a game is unsuccessful, the next time you can play again with the same licensing results. But we still like the system automatically generated ... The simplest way is to take advantage of the system time (almost all people do), because the value of time changes with time, run two times, generally do not appear the previous and the same situation after the next time (NULL) Returns an integer representing the current system time (it is said to be in time.h, which is reported as the number of seconds from January 1, 1970 to the present, some of which are UNIX years old, not knowing whether the two are a day ...): (and the other is too troublesome to write time (0)). Let's write it this way:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void Main ()
{

Srand ((int) time (0));
for (int x=0;x<10;x++)
printf ("%d\n", (rand ());
}

It is said that if the software has been open for two days, the seeds will be 1/(60*60*24) may be repeated, although this for the average person is absolutely enough, but even if the person is not comfortable, so I open on the internet to have so written:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/timeb.h>

void Main (void)
{
int i;
unsigned int seedval;
struct TIMEB timebuf;
Ftime (&AMP;TIMEBUF);
Seedval= ((((unsigned int) timebuf.time&0xffff) +
(unsigned int) timebuf.millitm) ^
(unsigned int) timebuf.millitm);
Srand ((unsigned int) seedval);
for (I=0;i<10;++i)
printf ("%6d\n", Rand ());
}

(Here's an explanation for it, but I'm not too sure, but I'm not too clear on that.)

"The above program first calls _ftime () to check the current time and put its value in the struct member Timebuf.time, the current time value is calculated in seconds starting January 1, 1970. After _ftime () is called, the number of milliseconds that the current second has spent in the member millitm of the struct timebuf is also deposited, but in DOS the number is actually calculated in 1% seconds. Then, the number of milliseconds and seconds are added, and the number of milliseconds is different or operation. Of course, the two members of the structure can also be more calculated to control the range of Seedval value, and further enhance its randomness, but the above example of the logical operation is sufficient. ”

Look at the following code:

void Main ()
{
for (int i=0;i<100000;i++)
{
Srand ((unsigned) time (NULL));
printf ("%d\n", Rand ());
}
}

Why do you always generate a number??? Because the program generates a random number before it calls a srand, and because the computer is running fast, every time it gets is the same (time is less accurate, only 55ms). This is equivalent to using the same seed to produce a random sequence, so the resulting random number is always the same. Put the srand outside the loop to see:
Srand ((unsigned) time (NULL));
for (int i=0;i<100000;i++)
Problem solved:)

Since the generated is a random integer evenly distributed between the 0-rand_max (let's just create the ideal random number bar), then to generate a random number between 0-x (including 0 excluding x), change rand () to RAND ()/(double) rand_max*x, To generate X-y between (including × excluding y) is rand ()/(double) rand_max* (y-x) +x. But if you want to have an integer between 0-10, many people would write:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void Main ()
{

Srand ((int) time (0));
for (int x=0;x<10;x++)
printf ("%d\n", (rand ()%10);
}

The X-y is rand ()% (y-x) +x

??? Know a little bit of probability that this writing, will make the resulting sequence distribution uneven, but everyone really like to write this ... Because the value of x is relatively small, the rand_max is comparatively large, and the generated sequence is not too large, but also to solve the problem of low accuracy (such as some game goals, the legend of the game in the mine-type encounter enemy is implemented with RAND (). When the protagonist walks on the map, there are 32 of creeps and fights. It is the implementation of the main character of the position of 0, the protagonist every step, the variable plus 1, when the variable = = randomly obtained number, creeps appear, so write enough ...

The algorithm for generating non-repetitive random numbers with m less than N is discussed below.

I think the algorithm structure is very important, but the sentence structure is also very important, so I like an algorithm to give the structure of multiple statements ...

The easiest fool algorithm to generate these random numbers, each producing one, is compared to the previous random number and, if repeated, is re-generated:

Algorithm one (1)

Srand ((unsigned) time (NULL));

for (j = 0; J < m; J + +) {

A:A[J] = rand ()% n;
for (i=0;i<j;i++) {if (A[i]==a[j]) goto A;}

Early learning programming like to use GOTO statement, because the past algorithm is represented by a flowchart, with Goto can be directly translated, and the Loop statement development is not perfect, just as a supplement to the conditional branch, if the conditional branch arrow upward is a loop, And Goto can achieve the structure that the past cycle cannot achieve, and form a very clever loop crossover. So in the past it was generally thought that there were two kinds of structure, order and branching, and the loop was a special case of branching. However, the break and continue statements make it possible to implement these constructs, and later find that the use of Goto can cause many problems in maintenance and debugging, so the loop gradually replaces the Goto and makes the program more hierarchical. Now programming is not recommended to use Goto, if the use of Goto will also be considered poor programming ... Go to the point and remove the goto:

Algorithm One (2)

Srand ((unsigned) time (NULL));

j=0;
while (J<M)
{
A[J] = rand ()% n;
for (i=0;i<j;i++) {if (a[i]==a[j]) break;}
if (i<j) continue;

J + +
}

But later it is recommended to use a For loop, which makes the loop condition compact:

Algorithm One (3)

Srand ((unsigned) time (NULL));

for (j=0;j<m;j++)

{A[j]=rand ()%n;

for (i=0;i<j;i++)

{if (A[i]==a[j])

{I=-1;a[j]=rand ()%n;}

}

}

But this is a very stupid method, and the comparison of the number of linear growth, the more the next number of times ... Another idea is to generate one and remove it from it, and you can do it without repeating it:

Algorithm two (1)

for (i=0;i<n;i++)

a[i]=i+1;

for (i=0;i<m;i++)

{J=rand ()% (n-i);

B[I]=A[J];

for (k=j;k<n-i-2;k++)

A[K]=A[K+1];

}

B[] is a generated random sequence

It's too much trouble to do so, the generated directly to make a mark is not OK?

Algorithm three (1-1)

I=rand ()%m;

A[i]=1;b[0]=i;

for (j=1;j<m;j++)

{for (I=rand ()%m;a[i]==1;i=rand ()%m);

B[j]=i;a[i]=1;

}

Write it tight, straight:

Algorithm three (1-2)

for (j=0;j<m;j++)

{for (I=rand ()%m;a[i]==1;i=rand ()%m);

B[j]=i;a[i]=1;

}

But I see the more concise:

int n= a value;

int a[n]={0};

for (i=1;i<=n;i++)

{while (A[x=rand ()%n]);

A[x]=i;

}

This loop-free while guarantee a[m] is the initialized 0 state. This generates N, we only take M, which is too wasteful to combine:

int n= A value, m= a value;

int A[n]={0},b[m]

for (i=1;i<=n;i++)

{while (A[x=rand ()%n]);

B[i]=x;a[x]=1;

}

But people are always uncomfortable, who has a better approach to this algorithm?

This algorithm gets to the back, the higher the likelihood of encountering the elements that have been used, the more repetitions, but when M is small it is fine:)

Isn't that so satisfying? Look at the following:

Algorithm four (1)

for (i=0;i<n;i++)

a[i]=i+1;

for (i=n-1;i>0;i--)

{W=rand ()%i;

T=a[i];

A[I]=A[W];

a[w]=t;

}

This algorithm is very good, some people will suspect its randomness, but personally think it is not a problem, the second line in order to fill the entire array with 0 to N, the third line, is randomly generated from 0 to n-2 the subscript, the subscript element value with the n-1 subscript element value Exchange, has been carried out to the subscript 1 element. So it only needs to traverse once to produce all the random numbers.

But this generates n random numbers less than n, we just need M, plus two more sentences:

for (i=0;i<m;i++)

B[i]=a[i];

B[] is a generated random sequence

If M and n are close, or equal is the best, it may not be ... Change it:

Algorithm four (2)

for (i=0;i<n;i++)

a[i]=i+1;

for (i=0;i<m;i++)

{W=rand ()%n;

T=a[i];

A[I]=A[W];

a[w]=t;

}

But the condition in turn, if M is far less than n is OK, if close, its randomness has a problem (why?) ), and then change:

Algorithm four (3)

for (i=0;i<n;i++)

a[i]=i+1;

for (i=0;i<m;i++)

{W=rand ()% (n-i) +i;

T=a[i];

A[I]=A[W];

a[w]=t;

}

This will be foolproof ...

"Go" about C language generation of non-repeating random numbers

Related Article

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.