• 0

[C] random double between 0 and 1


Question

Hello all,

Im a newbie to C and I am not figuring out how to make a function that will generate a double between 0 and 1...

I KNOW NOTHING ABOUT C but managed to get a hello world work...

I tries this function but i think it's not working properly:

float_number = (float) rand()/RAND_MAX;

as when i try to display the num with this forloop it's getting me huge negative or positive numbers

		for(i = 0; i < 500; i++){
			printf("%d\n",  float_number);
		}

another thing, what should i add to the code so i dont allow the program to exit directly after execution and so the command prompt stays opened so i can see the results?

Thanks in advance.

Elio

Link to comment
https://www.neowin.net/forum/topic/980266-c-random-double-between-0-and-1/
Share on other sites

21 answers to this question

Recommended Posts

  • 0
  On 04/03/2011 at 17:36, Veiva said:

You should use "%f" for floating point numbers, not "%d."

On the second question, some IDEs will prevent the program from closing immediately. Otherwise something simple like fgetc(stdin) will work.

Thanks for the fgetc(stdin) it worked...

the random number gives always the same number :s

think i passed through this earlier today on google.. will double check...

10x anw

  • 0

That is because by default the rand function is seeded with 0. Check this out: http://www.cplusplus.com/reference/clibrary/cstdlib/srand/ the most popular solution is to seed it with the system time. That should give you different pseudo random sequences for each run.

  • 0

for(i = 0; i < 500000; i++){
			double_number = (double) rand()/RAND_MAX;
				srand (time(NULL)); // this is used to seed the random number by the system time
			printf("%f\n",  double_number);
		}

The thing is i need to generate a huge number of random doubles in a for loop...

i hate 2 problems:

  1. Time interval in the loop is verry small, the number is slightly changing every one second which is bad
  2. The generated numbers are very closed to each other,,, and i dont want that :(

OKay fixed it :)

\

for(i = 0; i < 50; i++){
			double_number = (double) rand()/RAND_MAX;
				srand (time(NULL)+rand()); // this is used to seed the random number by the system time
			printf("%f\n",  double_number);
		}

  • 0
  On 04/03/2011 at 18:39, Veiva said:

Call srand(time(NULL)) once before the loop. This will continue to generate random numbers. You don't need to call it every time.

Also, since you're using double precision instead of single, you really should use "%Lf" in the printf statement.

Okay thanks...

It's actually my first C program :-)

  • 0
  On 04/03/2011 at 21:15, eliokh said:

I KNOW NOTHING ABOUT C

Cool. So maybe one of the first things that you should learn is that rand() does not, under any stretch of your imagination, generate a random number. Pound that idea into your head. It doesn't matter what you seed it with, either, but seeding with the current time is what everybody does and it almost always causes a problem at some point. Someone could use a number of methods to predict, both ahead of time and after the fact, the exact 50 doubles that your function would generate. If you run your program more than once within 1 second, it will generate the same sequence of 50 doubles. Or if two people run your program within a second of each other they will both generate the same sequence. If you need a range of doubles other than 0.0 to 1.0, I guarantee you'll do it wrong. Your rand() function will start to repeat itself after about 32,000 calls. There are plenty of other pitfalls. These things may or may not matter to you, but the reality is that this kind of thing is a bit complicated.

There is no good cross-platform way to reliably generate random numbers without using C++ or using a C library. This is especially true if you're looking for something like numbers that are unpredictable, has a special distribution (normal, uniform, poisson, etc), want them in a range that's not evenly divisible by the size of the random numbers you are generating, or if you need a secure seed value.

If you're able to use C++ (which will compile C code as well), modern compilers support a set of random number generators that can generate random numbers in various distributions (random, normal distribution, even distribution, etc) using various algorithms (including unpredictable sources), with larger periods (the amount of times before the RNG starts repeating). That way you don't have to worry about clipping your range or accidentally creating an uneven probability for certain numbers (like lots of people do with "rand() % SOME_NUMBER"). For example, you can do this to reliably generate a random (meaning each double has an equal probability of being generated) double between 0.0 and 1.0, inclusive:

mt19937 engine(YOUR_SEED);
uniform_real<double> distribution(0.0, 1.0);
variate_generator<mt19937&, uniform_real<double> > gen(engine, distribution);

for (int i = 0; i < 50; i++)
    double rndDouble = gen();

You can generate more values than there are atoms in the visible universe before that generator repeats itself. Then getting other ranges, distributions, generators, or engines is as easy as switching them in.

Regardless of whether you can use C++, if you need a seed value, then please seed your rand function with something other than time(NULL); you can find countless forum posts where using time-based seeds causes some problem. On linux, just read a random value from "/dev/urandom". On Windows, you can use rand_s (which makes a call to the cryptographic RNG function, which is stupidly-named "SystemFunction036") if speed is a concern or use "rand_s" directly and simply skip the seeding process (since a cryptographic RNG, by definition, doesn't need a user-supplied seed value).

  • Like 2
  • 0
  On 04/03/2011 at 17:31, eliokh said:

another thing, what should i add to the code so i dont allow the program to exit directly after execution and so the command prompt stays opened so i can see the results?

you can use

system("PAUSE");

which is a call to the PAUSE instruction you can also call in cmd

  • 0

Okay thanks everyone...

I managed to make the assignment work...

it is part of the parallel programming course and we are trying to calculate the value of PI based on the mote carlo (somthing like that :p lol ) method...

and i need to take 100% random numbers.

The thing is we did it sequentially just to get used to C as we are JAVAists

and the next step would be parallelizing it...

thanks again

  • 0

//check if a point is inside a circle
		for( i=0; i<number_of_points; i++){   //number_of_points = 99999999;
			double current_x = points_xes[i];
			double current_y = points_yies[i];    //is this causing huge memory usage?


			if((current_x * current_x) + (current_y * current_y) <= 1){
				count_inside++;
			}else{
				count_outside++;
			}

I THINK THIS PART OF CODE IS USING MY RAMS... AFTER EXECUTION THE RAM USAGE INCREASES BY 1 GB... do you think this loop is the reason? as i have huge number of points and i'm creating 2 new doubles in each iteration?

how can i fix this?

Should i set them to null in the end of the loop and later "garbage collect them"?? (is there garbage collection in c?)

thanks

  • 0

If you're storing almost 100 million doubles in memory, yes that will tend to use up a lot of memory at at least 8 bytes a pop.

There is garbage collection in C, but it's manual. You use the free(my_ptr) function where my_ptr is something that was created using malloc or calloc (like the huge arrays you're using). You don't perform garbage collection on regular doubles. It also shouldn't be recreating them, but you can move the double current_x to oustide the loop and then just do current_x = if somehow that's the case.

  • 0

You are not creating two new doubles each iteration. You are re-using the same doubles that live on the stack.

However, assuming the code works correctly, points_xes and points_yies contain at least 100 million elements. Assuming they are doubles, and a double is 8 bytes, that is 2 x 8 bytes x 100 million = 1600MB. The memory allocation happens before the loop, in some code you haven't shown here.

  • 0
  On 05/03/2011 at 19:08, Dr_Asik said:

in some code you haven't shown here.

After seeing that 100,000,000 iteration loop, I'm not sure we want to see the other code. I also don't want to know if he's stack-allocating 100,000,000-length double arrays.
  • 0
  On 06/03/2011 at 11:59, boogerjones said:

After seeing that 100,000,000 iteration loop, I'm not sure we want to see the other code. I also don't want to know if he's stack-allocating 100,000,000-length double arrays.

#include<stdio.h>
#include<stdlib.h> //now i can use rand()

#include<time.h>
#include<string.h>


int i;
double double_number;
int number_of_points = 99999999;
double points_xes[99999999];
double points_yies[99999999];
int count_inside = 0; //count the number of points inside the circle
int count_outside = 0; //count the number of points outside the circle
double percentage_p_inside = 0; //percentate of the points inside the circle
double PI = 0; //the found value of PI


time_t start_time;
time_t end_time;




main()
{

		printf("Welcome to computing pi!, Elio's first C program.");
		printf("\n\nComputing PI based on %d",number_of_points);
		printf(" points.\n");

		start_time = time (NULL); //get the start time

		srand (time(NULL)+rand()); // this is used to seed the random number by the system time
		//computing the first number_of_points point and considering them as the "X" value for each point
		for(i = 0; i < number_of_points; i++){
			double_number = (double) rand()/RAND_MAX;

			points_xes[i] = double_number;
			//printf("%Lf\n",  double_number);
		}


		//computing the second number_of_points point and considering them as the "Y" value for each point
		for(i = 0; i < number_of_points; i++){
			double_number = (double) rand()/RAND_MAX;

			points_yies[i] = double_number;
			//printf("%Lf\n",  double_number);
		}



		//check if a point is inside a circle
		for( i=0; i<number_of_points; i++){
			double current_x = points_xes[i];
			double current_y = points_yies[i];


			if((current_x * current_x) + (current_y * current_y) <= 1){
				count_inside++;
			}else{
				count_outside++;
			}
		}



		printf("\nNumber of points inside: %d",count_inside);
		printf("\nNumber of points outside: %d", count_outside);

		//calculate the percentage of points inside the circle
		percentage_p_inside = (double)(count_inside)/(count_inside + count_outside);
		printf("\nPercentage of points inside the circle: %Lf",percentage_p_inside);


		PI = percentage_p_inside * 4;
		printf("\n\nPI = %Lf", PI);

		end_time = time(NULL);

		printf("\nPI calculated in: %d",(end_time-start_time));
		printf(" seconds.");

		fgetc(stdin); // just to avoid closing the command prompt after the excecution of the code.
}


here is the rest of the code...

I know it could be very bad in term of design but i told u it's my first c program and i done it all by myself.. they didnt give us any tutorial

it's just a university small hw... :p

10x

238423149.jpg

  • 0

I'm surprised the program even compiles or runs, although I've never tried putting that much data in static storage so I don't really know. Maybe someone with better knowledge of C can provide some precisions. Anyway, when you need large amounts of memory, use the heap (malloc() in C, new in C++). This will allow you to free it at runtime when you are done with it (free() in C, delete in C++), whereas static storage remains until program termination. See here for examples (in C++).

That being said, even using dynamic memory allocation isn't the way to go. Your basic problem here is that you try to generate all your points first, and then perform your statistical analysis on the whole bunch. What you could do, and it would use almost no memory, is to only work with a single point at a time, i.e. (pseudocode):

int pointsInsideCount = 0;
int pointsOutsideCount = 0;

for (number of points) { 
    double x = generateRandomDouble();
    double y = generateRandomDouble();
    if ((x, y) is inside circle) {
        ++pointsInsideCount;
    }
    else {
        ++pointsOutsideCount;
    }
}

This only ever uses the same two doubles, on the stack. 8 temporary bytes vs 1600 static MBs. Plus here it doesn't matter how many points you want, it'll take longer but it'll never use up any additional memory. :yes:

  • 0
  On 06/03/2011 at 21:17, Dr_Asik said:

I'm surprised the program even compiles or runs, although I've never tried putting that much data in static storage so I don't really know. Maybe someone with better knowledge of C can provide some precisions. Anyway, when you need large amounts of memory, use the heap (malloc() in C, new in C++). This will allow you to free it at runtime when you are done with it (free() in C, delete in C++), whereas static storage remains until program termination. See herefor examples (in C++).

That being said, even using dynamic memory allocation isn't the way to go. Your basic problem here is that you try to generate all your points first, and then perform your statistical analysis on the whole bunch. What you could do, and it would use almost no memory, is to only work with a single point at a time, i.e. (pseudocode):

int pointsInsideCount = 0;
int pointsOutsideCount = 0;

for (number of points) { 
    double x = generateRandomDouble();
    double y = generateRandomDouble();
    if ((x, y) is inside circle) {
        ++pointsInsideCount;
    }
    else {
        ++pointsOutsideCount;
    }
}

This only ever uses the same two doubles, on the stack.

yes u're right...

wat a bad design i was using :s loool

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.