Thread: rand and srand

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    42

    rand and srand

    Since calling srand in one library will affect the result of rand in all other libraries is it considered good practice to leave that responsibility to the main program? They would have a better idea of how it would affect the other libraries they are using.

    In other, higher level languages random number functions returns a number from 0 (inclusive) to 1 (exclusive). With this I can create a random integer within a certain range by multiplying. In C it doesn't work this way. Instead it returns a positive signed integer. So how would I distribute this random number into a certain range? My best thought is to turn it into a fractional number first, e.g.,

    r = rand() / (double)(1 + (unsigned int)RAND_MAX)

    Was curious if anyone had other ideas.

  2. #2
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    You should definitely read this:
    http://www.eternallyconfuzzled.com/articles/rand.html

    - Micko
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    42
    Ok, it appears their final recommended solution is effectively the same as what I had come up with, so that's good.

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    42
    I still don't much like their srand suggestion. Can I get the process ID? I personally would include that in the seed.

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I still don't much like their srand suggestion.
    Bummer. You can do whatever you want as long as the seed changes in a relatively unpredictable manner. However, taking a hash of the system time is both fast and portable. You won't get the same benefits from a more platform-dependent seeding scheme. From a different perspective, if two concurrent processes get a time seed simultaneously (or close enough so that the time_t value doesn't change), the seeds will be identical. If such a case is undesirable then you have no choice but to make sure that the seed is always unique.

    >Can I get the process ID? I personally would include that in the seed.
    Whatever floats your boat. This stuff isn't etched in stone, and a lot of the time a particular solution will reek of the author's personal preferences. And of course, my preferences are clarity and portability.
    My best code is written with the delete key.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    42
    >I still don't much like their srand suggestion.
    Bummer. You can do whatever you want as long as the seed changes in a relatively unpredictable manner. However, taking a hash of the system time is both fast and portable. You won't get the same benefits from a more platform-dependent seeding scheme. From a different perspective, if two concurrent processes get a time seed simultaneously (or close enough so that the time_t value doesn't change), the seeds will be identical. If such a case is undesirable then you have no choice but to make sure that the seed is always unique.
    Yes, such a case *is* undesirable, which is why I stated I don't like their srand suggestion.

    >Can I get the process ID? I personally would include that in the seed.
    Whatever floats your boat. This stuff isn't etched in stone, and a lot of the time a particular solution will reek of the author's personal preferences. And of course, my preferences are clarity and portability.
    Hence the question mark in my post. I'm not saying "use the pid", I'm saying "can I use the pid?". Is it easily accessible? Is it portable? In all that you wrote you didn't actually answer anything.

  7. #7
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    You can't get a pid portably, because C has no notion of process id at all. Under all *nix like systems (including those that claim to be POSIX) you can use getpid().

    The thing is, if you want serious, cryptographic strength randomness, you won't be using srand() or rand() in the first place, and if you didn't want serious randomness, you wouldn't bother using spectacularly convoluted method to create a unique and unpredictable seed. If you just want something unique, but doesn't matter if it's predictable, based on time(), or a higher resolution non-portable time method (like gettimeofday on *nix).

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    42
    The thing is, if you want serious, cryptographic strength randomness, you won't be using srand() or rand() in the first place, and if you didn't want serious randomness, you wouldn't bother using spectacularly convoluted method to create a unique and unpredictable seed.
    No, I'm not worried about cryptographic strength randomness. But there may be two or more instances of this program running at any given moment and I don't want such instances to produce identical results. Thus creating a seed from time alone is simply not good enough. I need to introduce some other variable into the mix. I do still want to maintain portability, so if pid is not an option then what is?

  9. #9
    Registered User
    Join Date
    Sep 2005
    Location
    Sydney
    Posts
    60
    The function getpid() will give you the PID of the current process; you will need to #include <sys/types.h> and <unistd.h>.

    Under Unix anyway. Windows, I have no idea.

    edit: cwr: oops, didn't mean to repeat what you said. :P I should refresh the page before posting I suppose...
    Last edited by lemnisca; 10-18-2005 at 08:10 AM.

  10. #10
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Yes, such a case *is* undesirable, which is why I stated I don't like their srand suggestion.
    I got that impression, but thanks for explaining it anyway. However, since I wrote that article, I felt the need to clarify for people who might read your statement and think that somehow my suggestion was wrong.

    >I'm not saying "use the pid", I'm saying "can I use the pid?".
    You don't seem to get that you can basically do anything you want. So for any question that follows the pattern of "Can I do <xxx>", the answer is invariably "Yes!". But, since seeding rand with the pid is platform-dependent, it's off-topic for this forum until you mention your OS. At that point we'll either direct you to a more appropriate forum, or some kind soul will answer your question.

    >Is it easily accessible? Is it portable?
    Yes, it's usually easily accessible. No, it's not portable.

    >In all that you wrote you didn't actually answer anything.
    I answered your question thoroughly given the incomplete information you offered (and continue to offer) us. Maybe you should spend more time coming up with a smart question and less time complaining that the answer wasn't exactly what you wanted.

    >I do still want to maintain portability, so if pid is not an option then what is?
    What you want is a unique seed for each run of the program, even if there could be multiple runs simultaneously. Not only does this make a non-portable assumption from the start, it's also awkward to do portably. You're better off separating the non-portable part from the rest of the program. You seem to be making a common misconception about what portability is.

    p.s. You might want to tone down the attitude until we like you better, because it's not ingraciating you to us.
    My best code is written with the delete key.

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    42
    >Yes, such a case *is* undesirable, which is why I stated I don't like their srand suggestion.
    I got that impression, but thanks for explaining it anyway. However, since I wrote that article, I felt the need to clarify for people who might read your statement and think that somehow my suggestion was wrong.
    Sorry, but you made it sound like you did not get that impression. Your attempt to clarify the article, however useful it may be to others, was posted as a reply to _me_. This made it sound like you were telling me I should use the time hashing method anyway. Thus it seemed like I needed to reiterate to you why it would not work.
    >I'm not saying "use the pid", I'm saying "can I use the pid?".
    You don't seem to get that you can basically do anything you want. So for any question that follows the pattern of "Can I do <xxx>", the answer is invariably "Yes!".
    I guess I was looking for people to expound just a little bit into not only how to use the pid but also if i should or shouldn't use the pid. (Fortunately cwr and lemnisca provided this information.)
    I answered your question thoroughly given the incomplete information you offered
    You definitely did not answer my question thoroughly. Most of what you wrote was just you trying to defend your article. The only response you gave that was actually meant for me was "Whatever floats your boat," which is not a helpful response, btw.
    ...even if there could be multiple runs simultaneously. Not only does this make a non-portable assumption from the start, it's also awkward to do portably
    Holy !@#$. Fine. Take simultaneously out of the sentence. Pretend the program will be fully executed two times within a single second. (Running a program two separate times is portable, yes?) Creating a seed based on just time will cause both executions to produce identical results. (This is bad.) So what is a fast, easy, portable solution to this?
    Last edited by the pooper; 10-18-2005 at 09:13 AM.

  12. #12
    Registered User TactX's Avatar
    Join Date
    Oct 2005
    Location
    Germany.Stuttgart
    Posts
    65
    You could use the value returned by malloc() as your seed. You can at least be sure that the result ist different when the program runs twice at the same time. And of course you can combine thast with other methods (time(NULL)).

  13. #13
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Ha...beaten. I was going to suggest a similar setup using new, but then I realized that this was the C forum.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    42
    You could use the value returned by malloc() as your seed. You can at least be sure that the result ist different when the program runs twice at the same time.
    It's a good idea, and I had also thought it might work, but when I tried it each run of the program would still end up mallocing the same block of memory. And so the pointer it returns and, obviously, the unitialized data it points to ends up being the same across separate executions.

  15. #15
    Registered User TactX's Avatar
    Join Date
    Oct 2005
    Location
    Germany.Stuttgart
    Posts
    65
    Then you could read eg. the first integer from the "uninitialised" data and increment it. Then even if malloc() returns the same pointer for subsequent calls of your program, the "unititialised" data will always be different. O.K.?

Popular pages Recent additions subscribe to a feed