0

I don't think this is a duplicate because I've tried other SO answers and they don't work for me. When I run a program (seeded with time) I get a bunch of random numbers. Then a few seconds later I run the program again and get a similar bunch of random numbers.

srand(time(0));
for(int i=0; i<10; i++) {
    cout<<rand()<<"\n";
}

8603 55 3146 26251 14799 16799 28230 314 3602 9504

8639 19984 3044 28803 29955 27225 29699 882 21389 7411

As you can see the numbers are different, but really similar. The reason this won't work for me is because I'm converting it into a float between 0 and 1 (dividing by RAND_MAX). Time in seconds is ticking extremely slowly when I do that. On one run I could have 0.09245... and next I could have 0.0925... . I'm using these probabilities to make a blackjack AI, and I don't want the same patterns in betting to show up in subsequent executions.

I've looked many around a lot and tried to put the seed inside the loop, but that just printed the same number 10 times. Not sure how to make the numbers appear completely random from execution time. Thanks for your ideas

EDIT:

Using

    srand(rd());    
    for(int i=0; i<10; i++) {   
        cout<<generate()<<"\n";
    }

14514284786278117030 4620546740167642908 13109570281517897720 17462938647148434322 355488278567739596 7469126240319926998 4635995468481642529 418970542659199878 9604170989252516556 6358044926049913402

I think I get this exact same sequence every time I run it.

EDIT 2:

A little bit of background to clear up confusion. I'd like the distribution to be even but it's ok if it's not it's just my own practice no casino business. My original plan is have 6 characters have a hit/stay probability array for values 12-20. So like Jim would have [0.958367, 0.942123, 0.876655, 0.864322, 0.7543321, 0.653213, 0.201201, 0.12919, 0.00001] Made those numbers up. Let's say Jim had a hand of 14. So I get a random 0-1 number, and if it is less than 0.876655 then he'll hit. Winners after a 100 rounds will have their "genes" mixed and after maybe a 1000 cycles the perfect child will be naturally selected and the perfect hit/pass ratio will be formed. That's how come I noticed Pam or somebody would always hit: their random gen always fell at like 0.05 and so she hit no matter how good or bad her hand. I'm pretty much done, the only thing is fixing this random generator and another small bug dealing with betting money (unrelated I promise)

Script Kitty
  • 1,737
  • 5
  • 27
  • 47
  • Sorry meant to say similar. My bad, not trying to lie to you will edit – Script Kitty Aug 15 '15 at 01:45
  • The code is fine as it is, you're seeing similarities that aren't there or are just a coincidence. – samgak Aug 15 '15 at 01:46
  • 2
    `srand ()` and `random ()` are effectively toys at this point, the committee may even deprecate them. `C++11` has much better support using `std::uniform_*distribution`. See:http://stackoverflow.com/questions/19665818/best-way-to-generate-random-numbers-using-c11-random-library – Chad Aug 15 '15 at 01:47
  • I suggest you look into engines and distributions. – ChajusSaib Aug 15 '15 at 01:47
  • @samgak I ran it a bunch more times; in fact the reason I noticed it was because the AI was making the same blackjack moves over and over again until I pulled out the debugger. Normally such a correlation doesn't bother me, but just because I'm `/ RAND_MAX` – Script Kitty Aug 15 '15 at 01:48
  • I also don't get how "random but similar" is a problem. While `rand` is by far from the best distributed (and you would run a risk of being fired for using such in a real casino or other sensittive environment), random is random. Similar is fine. Significantly skewed/biased or repeating (eg. the same seed comes up) is not fine. It is doubtful the 'same sequence' is achieved on each run - except if the runs happen within the same second - due to a different, albeit primitive, time-based seed being supplied. – user2864740 Aug 15 '15 at 02:10
  • Anyway, if you ever get 'the same number N times' in a row with a random function then it is probably used wrong - a good candidate to look for is incorrect re-setting the seed / PRNG state. – user2864740 Aug 15 '15 at 02:15
  • @user2864740 Right I hear what you're saying and normally I'd just mod it or something. But I want it to be between 0-1 and other SO answers say "just divide by RAND_MAX". So take 8603 / 32767 vs 8639 / 32767 and then Dwight is always going to be hitting on his first turn. Hope I said that right or did I misunderstand? – Script Kitty Aug 15 '15 at 02:17
  • 1
    Who cares what values are if they are random? Random is random. As previously stated, rand is not the best, and also using the divide by max is biased, but the results should still be "undetectable" with eyeball tests. Random is random. Generate many sequences and plot the distribution to see if (and to what extent) there is a problem; don't rely on eyeball-association for arguing this one way or the other. – user2864740 Aug 15 '15 at 02:21
  • @ScriptKitty Anyway, maybe there is a problem in using random directly - and not using it to shuffle a deck, as done in real life. I've no idea how much this affects bias or distribution or whatnot, but I believe that treating the deck(s) as a closed set is the only 'trivially correct' approach for dealing with card games. – user2864740 Aug 15 '15 at 02:25
  • @user2864740 I guess so, the only reason it bothers me is I restart the program often and for each of my 6 characters, they either hit or fold and seeding time moves so slowly. Converting to float 0-1 makes it such that a LOT of time would have to pass before they stop hitting every time. Also, I should be clear I'm not shuffling the deck (I have a de-que being shuffled with `random_shuffle`). – Script Kitty Aug 15 '15 at 02:36
  • @Chad Thank you, that link ultimately was what I was looking for. Sorry it took so long, at the moment I was bent on minimizing functions I was unfamiliar with. But in the end, it was useful! – Script Kitty Aug 15 '15 at 02:59

2 Answers2

7

If possible, use std::random_device to get your seed, and std::mt19937_64 to generate your numbers. std::random_device is intended (but, unfortunately, not guaranteed) to use hardware to generate truly random numbers, so at least in a good implementation, it's quite random indeed (but fairly low bandwidth).

C++11 rendered rand and srand pretty much obsolete.

Here's a quite demo program:

#include <random>
#include <iostream>

int main() { 

    std::mt19937_64 gen{ std::random_device()() };
    std::uniform_real_distribution<double> dis{ 0.0, 1.0 };

    for (int i=0; i<10; i++)
        std::cout << dis(gen) << "\n";
}

At least with a reasonably decent implementation of the library, this should produce fairly solid results.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Hi I appreciate your answer so much, very useful! However for now I used this and ran it twice and it still has ball-park numbers that are close to each other (will edit new data). Additionally the numbers are huge, do you know off the top of your head if there is a Max function for mt19937_64? I want them to be able to be between 0-1. Sorry if I'm missing something really obvious I'm just using rand and srand because that's what they taught us in school, I'm slow on the new trends. Thanks – Script Kitty Aug 15 '15 at 02:03
  • For numbers between 0 and 1, you want to use it with `std::uniform_real_distribution`. – Jerry Coffin Aug 15 '15 at 02:09
  • Actually I take that back. The every time I run it seed in or out of the loop it produces the EXACT same numbers. – Script Kitty Aug 15 '15 at 02:09
  • @ScriptKitty: Are you sure you're calling it correctly? See updated answer for a quick demo. If that demo program gives the same results on successive runs, then your implementation must be pretty horribly broken (I'd appreciate knowing what you're using). – Jerry Coffin Aug 15 '15 at 02:16
  • 2
    @ScriptKitty "Seeding in the loop" is uhh .. don't do that. A [good] PRNG, such as MT, is responsible for updating its own state and needs no help. – user2864740 Aug 15 '15 at 02:17
  • @JerryCoffin Sorry one second it's giving me syntax error @ dis{. – Script Kitty Aug 15 '15 at 02:22
  • I think I'm running C++11, IDE VisualStudio2010, and I pasted the demo at the very top of my main but unfortunately `dis{` shows error `Error 5 error C2470: 'dis' : looks like a function definition, but there is no parameter list; skipping apparent body` Thanks for your patience – Script Kitty Aug 15 '15 at 02:30
  • +1 I changed things around a little bit more and it worked (I was implementing it wrong). I had no idea what the { } was (I don't know C++ well). uniform_real_distribution also did the trick. Learned something awesome. – Script Kitty Aug 15 '15 at 03:02
1

Here's an example that does what I think you're wanting it to do:

//I'm guessing your time(0) was intended to be this?
static DWORD dwTime = timeGetTime();//static = value doesn't change
srand(dwTime);
while (1) //while the app is running, perform these actions.
{
    DWORD dwCurrTime = timeGetTime();
    for (int i = 0; i < 10; i++) {
        cout << rand() % 10 + 1 << "\n"; //1-10 
        //if dwTime + 500 milliseconds is less than current timeGetTime()
        //sleep, this allows you to check the code easily for repeats
        if (dwTime + 500 < dwCurrTime)
            Sleep(10000);
    }
}
Jeff
  • 56
  • 8
  • 2
    How does this answer the OP's question? They want to know why the numbers are similar. – NathanOliver Aug 15 '15 at 01:57
  • The question was how to make the numbers random after every execution, I gave an example that after my tests seem to be fairly random, along with a little bit of extra code that should make it easy for them to compare the numbers. – Jeff Aug 15 '15 at 02:02
  • 1
    It is time to let `rand()` go. the random number facilities of C++ were greatly expanded and enhanced with C++11 and it time to start using them. `rand()` is a very bad random number generator. also see: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3924.pdf – NathanOliver Aug 15 '15 at 02:22
  • Ahh I see, ty sir, I'd always just stuck with rand, figured it was decent enough at random generation. But, I'll start using stuff like mt19937 and uniform_int_dist now. – Jeff Aug 15 '15 at 02:28