C language srand does not require replay srand should not be placed in a loop as a pseudo-random function rand

Posted by Duey on Sat, 12 Feb 2022 05:31:36 +0100

Initial contact rand() function

_I learned three sort algorithms before: 1. Select Sort; 2. Bubble sort; 3. Insert sort; Sort the elements in the array using three algorithms. At first, the array was initialized with 0 ~ n ascending order, then descending order to n ~ 0, which was almost meaningful. To show "authenticity", we decided to use rand() to assign the array.

_At this time, we do not know that rand() is pseudo-random, only that it can be "random" number. Later, we slowly learned that rand() needs to initialize seed srand(seed) before calling it (even if it is not initialized, the system will default to seed seed 1), and the seed function srand() is actually a collection of several "random number sequences", so when seed seed seed seed seed seed seed seed seed seed seed seed is determined, The sequence of random numbers returned by a call to RAND () is also determined each time the program starts.

_Random number sequence returned by rand() under the same seed

For example, write a program randTest:

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

int main()
{
	short i;

    srand(1);
    for(i=0; i<1000; i++)
        printf("%d, ", rand());

    return 0;
}

  
_Each time a program is compiled and run, the results are the same. Although the computer is restarted or shut down, the output of rand() with seed seed 1 will not be changed:

41, 18467, 6334, 26500, 19169, 15724, 11478, 29358, 26962, 24464, 5705, 28145, 23281, 16827, 9961, 491, 2995, 11942, 4827, 5436, 32391, 14604, 3902, 153, 292, 12382, 17421, 18716, 19718, 19895, 5447, 21726, 14771, 11538, 1869, 19912, 25667, 26299, 17035, 9894, 28703, 23811, 31322, 30333, 17673, 4664, 15141, 7711, 28253, 6868, 25547, 27644, 32662, 32757, 20037, 12859, 8723, 9741, 27529, 778, 12316, 3035, 22190, 1842, 288, 30106, 9040, 8942, 19264, 22648, 27446, 23805, 15890, 6729, 24370, 15350, 15006, 31101, 24393, 3548, 19629, 12623, 24084, 19954, 18756, 11840, 4966, 7376, 13931, 26308, 16944, 32439, 24626, 11323, 5537, 21538, 16118, 2082, 22929, 16541, 4833, 31115, 4639, 29658, 22704, 9930, 13977, 2306, 31673, 22386, 5021, 28745, 26924, 19072, 6270, 5829, 26777, 15573, 5097, 16512, 23986, 13290, 9161, 18636, 22355, 24767, 23655, 15574, 4031, 12052, 27350, 1150, 16941, 21724, 13966, 3430, 31107, 30191, 18007, 11337, 15457, 12287, 27753, 10383, 14945, 8909, 32209, 9758, 24221, 18588, 6422, 24946, 27506, 13030, 16413, 29168, 900, 32591, 18762, 1655, 17410, 6359, 27624, 20537, 21548, 6483, 27595, 4041, 3602, 24350, 10291, 30836, 9374, 11020, 4596, 24021, 27348, 23199, 19668, 24484, 8281, 4734, 53, 1999, 26418, 27938, 6900, 3788, 18127, 467, 3728, 14893, 24648, 22483, 17807, 2421, 14310, 6617, 22813, 9514, 14309, 7616, 18935, 17451, 20600, 5249, 16519, 31556, 22798, 30303, 6224, 11008, 5844, 32609, 14989, 32702, 3195, 20485, 3093, 14343, 30523, 1587, 29314, 9503, 7448, 25200, 13458, 6618, 20580, 19796, 14798, 15281, 19589, 20798, 28009, 27157, 20472, 23622, 18538, 12292, 6038, 24179, 18190, 29657, 7958, 6191, 19815, 22888, 19156, 11511, 16202, 2634, 24272, 20055, 20328, 22646, 26362, 4886, 18875, 28433, 29869, 20142, 23844, 1416, 21881, 31998, 10322, 18651, 10021, 5699, 3557, 28476, 27892, 24389, 5075, 10712, 2600, 2510, 21003, 26869, 17861, 14688, 13401, 9789, 15255, 16423, 5002, 10585, 24182, 10285, 27088, 31426, 28617, 23757, 9832, 30932, 4169, 2154, 25721, 17189, 19976, 31329, 2368, 28692, 21425, 10555, 3434, 16549, 7441, 9512, 30145, 18060, 21718, 3753, 16139, 12423, 16279, 25996, 16687, 12529, 22549, 17437, 19866, 12949, 193, 23195, 3297, 20416, 28286, 16105, 24488, 16282, 12455, 25734, 18114, 11701, 31316, 20671, 5786, 12263, 4313, 24355, 31185, 20053, 912, 10808, 1832, 20945, 4313, 27756, 28321, 19558, 23646, 27982, 481, 4144, 23196, 20222, 7129, 2161, 5535, 20450, 11173, 10466, 12044, 21659, 26292, 26439, 17253, 20024, 26154, 29510, 4745, 20649, 13186, 8313, 4474, 28022, 2168, 14018, 18787, 9905, 17958, 7391, 10202, 3625, 26477, 4414, 9314, 25824, 29334, 25874, 24372, 20159, 11833, 28070, 7487, 28297, 7518, 8177, 17773, 32270, 1763, 2668, 17192, 13985, 3102, 8480, 29213, 7627, 4802, 4099, 30527, 2625, 1543, 1924, 11023, 29972, 13061, 14181, 31003, 27432, 17505, 27593, 22725, 13031, 8492, 142, 17222, 31286, 13064, 7900, 19187, 8360, 22413, 30974, 14270, 29170, 235, 30833, 19711, 25760, 18896, 4667, 7285, 12550, 140, 13694, 2695, 21624, 28019, 2125, 26576, 21694, 22658, 26302, 17371, 22466, 4678, 22593, 23851, 25484, 1018, 28464, 21119, 23152, 2800, 18087, 31060, 1926, 9010, 4757, 32170, 20315, 9576, 30227, 12043, 22758, 7164, 5109, 7882, 17086, 29565, 3487, 29577, 14474, 2625, 25627, 5629, 31928, 25423, 28520, 6902, 14962, 123, 24596, 3737, 13261, 10195, 32525, 1264, 8260, 6202, 8116, 5030, 20326, 29011, 30771, 6411, 25547, 21153, 21520, 29790, 14924, 30188, 21763, 4940, 20851, 18662, 13829, 30900, 17713, 18958, 17578, 8365, 13007, 11477, 1200, 26058, 6439, 2303, 12760, 19357, 2324, 6477, 5108, 21113, 14887, 19801, 22850, 14460, 22428, 12993, 27384, 19405, 6540, 31111, 28704, 12835, 32356, 6072, 29350, 18823, 14485, 20556, 23216, 1626, 9357, 8526, 13357, 29337, 23271, 23869, 29361, 12896, 13022, 29617, 10112, 12717, 18696, 11585, 24041, 24423, 24129, 24229, 4565, 6559, 8932, 22296, 29855, 12053, 16962, 3584, 29734, 6654, 16972, 21457, 14369, 22532, 2963, 2607, 2483, 911, 11635, 10067, 22848, 4675, 12938, 2223, 22142, 23754, 6511, 22741, 20175, 21459, 17825, 3221, 17870, 1626, 31934, 15205, 31783, 23850, 17398, 22279, 22701, 12193, 12734, 1637, 26534, 5556, 1993, 10176, 25705, 6962, 10548, 15881, 300, 14413, 16641, 19855, 24855, 13142, 11462, 27611, 30877, 20424, 32678, 1752, 18443, 28296, 12673, 10040, 9313, 875, 20072, 12818, 610, 1017, 14932, 28112, 30695, 13169, 23831, 20040, 26488, 28685, 19090, 19497, 2589, 25990, 15145, 19353, 19314, 18651, 26740, 22044, 11258, 335, 8759, 11192, 7605, 25264, 12181, 28503, 3829, 23775, 20608, 29292, 5997, 17549, 29556, 25561, 31627, 6467, 29541, 26129, 31240, 27813, 29174, 20601, 6077, 20215, 8683, 8213, 23992, 25824, 5601, 23392, 15759, 2670, 26428, 28027, 4084, 10075, 18786, 15498, 24970, 6287, 23847, 32604, 503, 21221, 22663, 5706, 2363, 9010, 22171, 27489, 18240, 12164, 25542, 7619, 20913, 7591, 6704, 31818, 9232, 750, 25205, 4975, 1539, 303, 11422, 21098, 11247, 13584, 13648, 2971, 17864, 22913, 11075, 21545, 28712, 17546, 18678, 1769, 15262, 8519, 13985, 28289, 15944, 2865, 18540, 23245, 25508, 28318, 27870, 9601, 28323, 21132, 24472, 27152, 25087, 28570, 29763, 29901, 17103, 14423, 3527, 11600, 26969, 14015, 5565, 28, 21543, 25347, 2088, 2943, 12637, 22409, 26463, 5049, 4681, 1588, 11342, 608, 32060, 21221, 1758, 29954, 20888, 14146, 690, 7949, 12843, 21430, 25620, 748, 27067, 4536, 20783, 18035, 32226, 15185, 7038, 9853, 25629, 11224, 15748, 19923, 3359, 32257, 24766, 4944, 14955, 23318, 32726, 25411, 21025, 20355, 31001, 22549, 9496, 18584, 9515, 17964, 23342, 8075, 17913, 16142, 31196, 21948, 25072, 20426, 14606, 26173, 24429, 32404, 6705, 20626, 29812, 19375, 30093, 16565, 16036, 14736, 29141, 30814, 5994, 8256, 6652, 23936, 30838, 20482, 1355, 21015, 1131, 18230, 17841, 14625, 2011, 32637, 4186, 19690, 1650, 5662, 21634, 10893, 10353, 21416, 13452, 14008, 7262, 22233, 5454, 16303, 16634, 26303, 14256, 148, 11124, 12317, 4213, 27109, 24028, 29200, 21080, 21318, 16858, 24050, 24155, 31361, 15264, 11903, 3676, 29643, 26909, 14902, 3561, 28489, 24948, 1282, 13653, 30674, 2220, 5402, 6923, 3831, 19369, 3878, 20259, 19008, 22619, 23971, 30003, 21945, 9781, 26504, 12392, 32685, 25313, 6698, 5589, 12722, 5938, 19037, 6410, 31461, 6234, 12508, 9961, 3959, 6493, 1515, 25269, 24937, 28869, 58, 14700, 13971, 26264, 15117, 16215, 24555, 7815, 18330, 3039, 30212, 29288, 28082, 1954, 16085, 20710, 24484, 24774, 8380, 29815, 25951, 6541, 18115, 1679, 17110, 25898, 23073, 788, 23977, 18132, 29956, 28689, 26113, 10008, 12941, 15790, 1723, 21363, 28, 25184, 24778, 7200, 5071, 1885, 21974, 1071, 11333, 22867, 26153, 14295, 32168, 20825, 9676, 15629, 28650, 2598, 3309, 4693, 4686, 30080, 10116, 12249

  
  

Reseeding, so that the program produces different random numbers each time it compiles and runs

_Because rand() returns the same sequence of random numbers when the seed is determined, it is necessary to replay the seed before rand(), that is, srand (time (NULL).

_time() function

The_time() function is contained in the header file time.h, this header file needs to be introduced before calling: #include <time.h>.

The function prototype of the_time() function is:time_t time(time_t *seconds), time_ T is the size of long (that is, 8 bytes) and can initialize a time_ The variable sec of the T data type, which stores the current time, such as:time_t sec=time(NULL);

_time(seconds) returns the time elapsed since 1970-01:00:00:00 to the parameter seconds, in seconds, with a return value of long and the data type of the parameter seconds also of long.

The_time() function is generally used to calculate the time between 1970-01:00:00 and the present (when the parameter seconds is 0 or'NULL').

_time() instance

_1. Return the days, hours, minutes, seconds from 1970-01 00:00:00 to the present (2022-02-11 16:49:20):

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

int main()
{
	time_t sec;	//It can also be written as long sec;
  	sec=time(NULL);
  	
	printf("1970-01-01 00:00:00 To date %ld Days; common %ld Hours; common %ld Minute; common %ld second", sec/86400, sec/3600, sec/60, sec));

    return 0;
}

  
_Output results:

1970-01-01 00:00:00 To date, 19034 days; 456824 hours; 27409489 minutes in total; 1644569360 seconds
Process returned 0 (0x0)   execution time : 0.011 s
Press any key to continue.

  
_2. With the void Sleep(DWORD dwMilliseconds) function, time(NULL) is output every second, and the Sleep function is contained in windows. In the H header file, the parameter is in milliseconds and the parameter type is DWORD (double word, two bytes in size, equivalent to short):

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

int main()
{
    printf("%ld\n", time(NULL));
    Sleep(1000);
    printf("%ld\n", time(NULL));
    Sleep(1000);
    printf("%ld\n", time(NULL));

    return 0;
}

  
_Output results:

1644572287
1644572288
1644572289

Process returned 0 (0x0)   execution time : 2.043 s
Press any key to continue.

  srand(time(NULL))

With so much padding, we finally reach the protagonist srand (time(NULL). From the previous knowledge, we know that time(NULL) will change over time. As long as the program does not run twice in the same second, the seeds will not be the same. Different seeds will produce different sequences of random numbers, so the first program randTest will not be the same.

_Modify the program randTest a little and add the header file#include <time. H>and #include <windows. H>, change the seed to time(NULL) to see if the two random number sequences are the same:

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

int main()
{
	short i;

	/*rand sequence of first seeding*/
    srand(time(NULL));
    for(i=0; i<1000; i++)
        printf("%d, ", rand());

	/*rand sequence replayed after one second of dormancy*/
	printf("\n\n Random number of second seeding:\n");
	Sleep(1000);
	srand(time(NULL));
    for(i=0; i<1000; i++)
        printf("%d, ", rand());

    return 0;
}

_From the output results, it can be seen that the random number sequences produced by two srand s are different:

  
  

Accidentally writes srand(time(NULL)) into the for loop

_After learning, practice and thinking, a brief analysis of rand and srand

_Although we know that srand corresponds to a sequence of random numbers, due to the lack of depth of understanding and thinking, we mistakenly believe that only the seeds of each rand are different, can we achieve "true randomness".

_In fact, rand is a pseudo-random number generator that returns a random number with a value between 0 and rand_ MAX (by looking at the stdlib.h source, RAND_MAX is defined as 0x7fff), while the random number sequence in the seed function srand is calculated from the seed seed seed seed seed seed through a formula, and the random number sequence appears to be "out of order", but it conforms to a certain rule (because it is calculated from the seed through a formula).

_stdlib. H source (right-click #include <stdlib.h> for any project main function, click Open #include file:'stdlib.h', open D:\CodeBlocksMinGW\x86_64-w64-mingw32\includestdlib.h):

  

_It is precisely because you know that srand is a sequence of random numbers calculated from seed and that Rand under the same seed can be calculated (although not by the human brain), that you want to call a different seed each time you call rand(). Here is an example of the error:

int a[100]={};
char n=100;
char i;

for(i=0; i<n; i++)
{
    srand(time(NULL));
    a[i]=rand();
}

  
_Output results:

21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 21765 
Process returned 0 (0x0)   execution time : 0.039 s
Press any key to continue.

  

_Analysis error

In my view, there are two errors in the code above.
_1. The time() function should not be placed in a loop.
_2. The srand() function may not be placed in a loop, although the starting point is to get a more "random" sequence to assign values to the array.

_For Question 1, the output shows that the whole program runs out in 0.039s only, so it takes less than 1 second to cycle 100 time s, or even 1,000 or 10,000 time s (the speed is also related to hardware), while the precision of time() function is 1 s. Sleep(1000) should be used to change seeds in each cycle. Hang up for 1s after each rand() before next seeding; Alternatively, use the GetTickCount() time function with millisecond precision and the QueryPerformanceFrequency() time function with microsecond precision instead of time(NULL).
  
_For Question 2, whether srand is not suitable for placing in a cycle, starting from Question 1, let's further consider that even if Sleep() function is used, even if a more accurate time function is used, if the cycle reaches 100,000,000, million, 0.01s will be wasted in each step of seeding, then a 100,000 cycle will waste 10,000 seconds in seeding, which is too horrible.
_Back to the beginning, why does srand stay in the loop because I don't think rand is "random enough". I have to use a more "random, disordered" method to make the number produced by rand more "random". So, even if I don't consider the waste of time, do I put rand in the loop more randomly? Is replacing seeds rand more random?

_Test ideas: The first step is to test whether rand under continuous seeds will appear the same number at the same location, so as to identify that even if rand is pseudo-random, it can be sufficient "random". Gets the value of time(NULL) to assign to the long variable sec0, records the rand values of sec0, sec1=sec0+1, sec2=sec0+2, sec3=sec0+3, assigns to the int s array a, b, c, D of 1000 length, and compares the elements a, b, c, d one by one.
  
_Step 2: Test whether rand will appear in the order of items a, b, c, d and i under the order change of four seeds sec0, sec1, sec2, sec3, or whether each refresh of the seed will start from item 0 and will not be "more random" as originally thought. There are four seeding functions in the loop, the seeds are sec0, sec1, sec2, sec3, and the results of rand 1000 times are printed. The values of a, b, c, d in the notebook are compared.

_First step code:

_1. Get sec0 to sec3 values first:

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

int main()
{
    time_t sec0, sec1, sec2, sec3;

    sec0=time(NULL);
    sec1=sec0+1;
    sec2=sec0+2;
    sec3=sec0+3;

    printf("sec0:%ld\nsec1:%ld\nsec2:%ld\nsec3:%ld\n\n",sec0, sec1, sec2, sec3);   //Print values of seed sec0, sec1, sec2, sec3
    
    return 0;
}

  
_Output results:

sec0:1644594655
sec1:1644594656
sec2:1644594657
sec3:1644594658

Process returned 0 (0x0)   execution time : 0.030s
Press any key to continue.

  

_2. Manually assign the values just obtained to sec0 through sec3, and then start the array assignment, comparing whether there are duplicates:

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

int main()
{
    int a[1000]={};
    int b[1000]={};
    int c[1000]={};
    int d[1000]={};
    time_t sec0, sec1, sec2, sec3;
    short i;

    sec0=1644594655;
    sec1=1644594656;
    sec2=1644594657;
    sec3=1644594658;

    /*Array a to d assignment*/
    srand(sec0);
    for(i=0; i<1000; i++)
        a[i]=rand();

    srand(sec1);
    for(i=0; i<1000; i++)
        b[i]=rand();

    srand(sec2);
    for(i=0; i<1000; i++)
        c[i]=rand();

    srand(sec3);
    for(i=0; i<1000; i++)
        d[i]=rand();

    /*Print a, b, c, d */
    for(i=0; i<1000; i++)
        printf("%-6d%-6d%-6d%-6d\n", a[i], b[i], c[i], d[i]);

    /*Contrast Repeated or Not*/
    for(i=0; i<1000; i++)
        if(a[i]==b[i] || a[i]==c[i] || a[i]==d[i] || b[i]==c[i] || b[i]==d[i] || c[i]==d[i])
            printf("Under Subscript %d Same everywhere\n", i);

    return 0;
}

  
_Output results: (partial screenshots)
_Beginning part:

  

End of_:
  
_From the comparison results, it can be seen that the continuous seeds, rand also do not have the same subscript repeated number, indicating that rand can be considered as a "random number" in a certain range.
  

_Step 2 code:

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

int main()
{
    time_t sec0, sec1, sec2, sec3;
    short i;

    sec0=1644594655;
    sec1=1644594656;
    sec2=1644594657;
    sec3=1644594658;


    for(i=0; i<1000; i++)
    {
        srand(sec0);
        printf("%-6d", rand());

        srand(sec1);
        printf("%-6d", rand());

        srand(sec2);
        printf("%-6d", rand());

        srand(sec3);
        printf("%-6d", rand());

        printf("\n");
    }

    return 0;
}

  
_Output result: The result is obvious, it is simply a random number that fails

  

Another "random" rand conjecture:

_Another guess is that the seed of a constant transformation: srand(rand() + i + rand()), even if Rand is the first number to take srand, as long as the seed is constantly changing, rand's arrival will not repeat, can it also be considered a "random number"? In fact, I think it's a bit like "masking your ears and stealing your bells and deceiving yourself". You can get a bunch of nearly random, disordered columns designed by the programmer. You just need to take out the numbers in the columns in Rand order. Are you "random" seeds every time? Would Rand produce a more "random" result? Don't forget to initialize srand before rand. The first srand(rand() + i + rand()) must be equivalent to srand(41 + i + 41)
  
  

Summary

_That's what we found in the recent use of srand and rand. I don't know if it's complete or not. In the process, srandom and srandom seem to be better than srand and rand. Keep working hard!!!

Topics: C