• 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.
  • Posts

    • It is fundamentally impossible to secure delete files, especially on newer HDDs and all SSDs. You never know how the controller firmware is going to layout data or copy data around to optimize access or invoke wear leveling. The only way to securely “delete” something is to put it on an encrypted file system and forget the encryption key, assuming any apps you open the files in don’t copy the files to a local cache on the boot volumes.
    • TBF, it has had PST support for quite a while now. But I still want them to add the ability to drag & drop between accounts / PSTs.
    • LibreOffice closes in on Office, leaves Windows 7/8 behind in 25.8 Beta 1 by David Uzondu The Document Foundation has released LibreOffice 25.8 Beta 1 for public testing on Linux, macOS, and Windows. This is the second pre-release for the 25.8 cycle and the foundation says that the final, stable version of LibreOffice 25.8 is expected to land at the end of August 2025. Starting off with Writer, LibreOffice's Word, the developers have finally addressed some long-standing annoyances, including a new command to easily insert a paragraph break right before a table. This beta also introduces a useful privacy feature in its Auto-Redact tool, letting you strip all images from a document with a single option. To use it, go to Tools and select the Auto-Redact option: The application has improved its ability to handle different languages for punctuation, preventing mix-ups in multilingual documents. Other notable improvements have also been made. A new hyphenation rule lets you choose to prevent a word from splitting at the end of a page, moving the whole line to the next page instead. Microsoft Word has had this feature for years now. The Navigator now displays a handy tooltip with word and character counts for headings and their sub-outlines. Scrolling behavior when selecting text has been improved, making it less erratic. A new command with a keyboard shortcut was added for converting fields into plain text. Calc gets a lot of new functions that bring it closer to its competitors like Excel, including TEXTSPLIT, VSTACK, and WRAPROWS. Impress now properly supports embedded fonts in PPTX files, which should reduce headaches when sharing presentations with PowerPoint users. Alongside these additions, the project is also cleaning house; support for Windows 7, 8, and 8.1 has been completely dropped. There are also smaller UI tweaks across the suite, like allowing a single click to enter rotation mode for objects in Writer and Calc. macOS users get better integration, with proper support for native full screen mode and new window management features from the Sequoia update. In terms of performance, the team has optimized everything from loading huge DOC files and XLSX spreadsheets with tons of conditional formatting to simply switching between sheets in Calc. These improvements should be noticeable, especially when working with complex documents. A new application-wide "Viewer mode" has also been implemented, which opens all files in a read-only state for quick, safe viewing. On a related note, The Document Foundation has joined efforts by the likes of KDE to encourage Windows 10 users to switch to Linux. Also, you might have heard that Denmark, in a bid to lessen its reliance on Microsoft, has decided to make a full switch to LibreOffice, with plans to begin phasing out Office 365 in certain ministries as early as next month. If you're interested in this release, you can read the full release notes and download the binaries for your platform: Windows, macOS (Intel | Apple Silicon), or Linux (DEB | RPM). You can also get the latest stable version from our software stories page.
  • Recent Achievements

    • Explorer
      Case_f went up a rank
      Explorer
    • Conversation Starter
      Jamie Smith earned a badge
      Conversation Starter
    • First Post
      NeoToad777 earned a badge
      First Post
    • Week One Done
      JoeV earned a badge
      Week One Done
    • One Month Later
      VAT Services in UAE earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      545
    2. 2
      ATLien_0
      227
    3. 3
      +FloatingFatMan
      160
    4. 4
      Michael Scrip
      113
    5. 5
      +Edouard
      104
  • Tell a friend

    Love Neowin? Tell a friend!