Is there a bug in the C++ random generator? - c++

I've written a small program at https://github.com/lub094/Roulette. It simulates a roulette and calculates the times a sequence of same color sectors with length n, has been reached. So if you spin it 4 times and you get RED, BLACK, BLACK, BLACK that will give you 2 sequences with lengths 1, and 1 sequence of lengths 2 and 3.
The problem comes when I spin it more than a million times. Then the longest sequence reached is absolutely always 15. I've tried it with 500 000 000 000 spins and yet again, the longest sequence is 15. I've done the math, I've tried it on java and this seems to be an abnormal behavior. I've tried putting the seed srand() in the main, in the constructor of the Roulette class and in the method calling rand(), but there seems to be no difference.
This is how I'm currently seeding the rand:
#include <iostream>
#include "Roulette.cpp"
int main() {
srand(time(nullptr));
Roulette roulette;
roulette.spin(10000000);
return 0;
}
In the class Roulette, I have the method getRandomColor() where I call the rand() method:
SectorColor getRandomColor() {
long long randomNumber = rand();
if (randomNumber % 2 == 0) {
return SectorColor::RED;
} else {
return SectorColor::BLACK;
}
}
I'm running it on windows on MinGW's latest version as for this date. The IDE I'm using is Eclipse.
I can't find any place where there could be a mistake, so thanks in advance if you try to investigate :)

Your problem is right here:
if (randomNumber % 2 == 0) {
return SectorColor::RED;
} else {
return SectorColor::BLACK;
}
It's well known that many implementations of rand() have very poor randomness in the lower bits. Try something like:
return (randomNumber & 1024)? SectorColor::BLACK : SectorColor::RED;
which uses bit 10 instead of bit 0.
Moving to the C++ template-based PRNGs, such as Mersenne Twister, would be even better.
Side note, naming include files with a .cpp extension is very bad style.

Related

C++ Password Generator Generates Same Password [duplicate]

In this rather basic C++ code snippet involving random number generation:
include <iostream>
using namespace std;
int main() {
cout << (rand() % 100);
return 0;
}
Why am I always getting an output of 41? I'm trying to get it to output some random number between 0 and 100. Maybe I'm not understanding something about how the rand function works?
You need to change the seed.
int main() {
srand(time(NULL));
cout << (rand() % 101);
return 0;
}
This srand thing also works for C.
See also:
http://xkcd.com/221/
For what its worth you are also only generating numbers between 0 and 99 (inclusive). If you wanted to generate values between 0 and 100 you would need.
rand() % 101
in addition to calling srand() as mentioned by others.
srand() seeds the random number generator. Without a seed, the generator is unable to generate the numbers you are looking for. As long as one's need for random numbers is not security-critical (e.g. any sort of cryptography), common practice is to use the system time as a seed by using the time() function from the <ctime> library as such: srand(time(0)). This will seed the random number generator with the system time expressed as a Unix timestamp (i.e. the number of seconds since the date 1/1/1970). You can then use rand() to generate a pseudo-random number.
Here is a quote from a duplicate question:
The reason is that a random number generated from the rand() function isn't
actually random. It simply is a transformation. Wikipedia gives a better
explanation of the meaning of pseudorandom number generator: deterministic
random bit generator. Every time you call rand() it takes the seed and/or the
last random number(s) generated (the C standard doesn't specify the algorithm
used, though C++11 has facilities for specifying some popular algorithms), runs
a mathematical operation on those numbers, and returns the result. So if the
seed state is the same each time (as it is if you don't call srand with a truly
random number), then you will always get the same 'random' numbers out.
If you want to know more, you can read the following:
http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/
http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/
You are not seeding the number.
Use This:
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
srand(static_cast<unsigned int>(time(0)));
cout << (rand() % 100) << endl;
return 0;
}
You only need to seed it once though. Basically don't seed it every random number.
random functions like borland complier
using namespace std;
int sys_random(int min, int max) {
return (rand() % (max - min+1) + min);
}
void sys_randomize() {
srand(time(0));
}
"srand(time(NULL));" as 1st line at "main()" won't help you if you're using "rand()" at static init. somewhere. You better create "struct rnd_init { rnd_init() { srand (time (nullptr)); } }" named whatever suits you, as a static var at the scope where "rand()" is being used: at some constructor, or whatever.

How do I properly develop a Probability System?

So I'm working on developing an online game, and one of the features of this game (like many other MMORPG's) is the drop system & upgrade system.
The drop system decides what items will drop from monsters when they are killed.
The upgrade system decides if an item will successfully upgrade to the next level or not.
They both need to be able to use probability to determine if:
An item Drops
An item upgrades successfully.
I've developed a system that generates a random number between 0 and 100000. In this system a 1% probability of either of the above happening would be represented by 1000. Similarly, a 0.5% would be 500... and 50% would be 50000.
Here is the guts of this code...
int RandomValueInRange(const int start, const int end)
{
std::random_device rd;
std::mt19937 generator(rd());
const int stable_end = ((end < start) ? start : end);
std::uniform_int_distribution<int> distribution(start, stable_end);
return distribution(generator);
}
Now in order to dermine if an item drops or upgrades sucecsfully, all I have to do is this...
const int random_value = RandomValueInRange(0, 100000);
const int probability = item.GetProbability();//This simply returns an integer stored in a config file which represents the probability of this item being dropped/upgraded.
if(random_value <= probability)
{
std::cout << "Probability Success!" << endl;
}
else
{
std::cout << "Probability Failed!" << endl;
}
I would expect the above to work, but for whatever reason it seems faulty... Players are able to get items that have a 0.1% probability with ease (something that should almost never happen!).
Does anyone know of a better system or how I can improve this system to truly follow the probability guidelines....
std::random_device rd;
std::mt19937 generator(rd());
...
return distribution(generator);
I think problem here, the std c++ library gives you uniform distribution
if you do reuse random_device and mt19937, but you recreate them each time,
it is not how that they should be used.
Save somewhere this std::random_device rd and this std::mt19937and this distribution
Ok, so the problem with your code is that you are choosing a random number between 0 and 100,000. Anyone can get between 1 and 100 with a bit of luck, because, if you think about it, 100 is a pretty big number and shouldn't be too hard to get.
Also, if you go back to Primary/Elementary (or whatever you want to call it) school maths books, you will see in the 'probability and chance' chapter, some questions like:
If there are 6 balls in a bag, 3 red, 1 green and 2 blue, then what is the chance of choosing a blue?
Of course, you would've answered 2/6 or 1/3. In C++, this can be changed to something like this:
#include <iostream>
#include <ctime>
#include <algorithm>
#include <random>
using namespace std;
// Be sure to have this in to get a truly random number
class MoreProbability {
// Be sure to have this in to get a truly random number
void GetProbability(int min, int max, int probability) {
const int arrayMax = max;
int probabilityArray[100000];
for (int i = 0; i < max; i++) {
if (i >= 0 && i <= probability) {
probabilityArray[i] = 1;
}
else {
probabilityArray[i] = 0;
}
}
// Arrays go from 0 to max-1 to account for the 0
std::random_shuffle(&probabilityArray[0], &probabilityArray[max - 1]);
// Check if the first element of the randomly shufffled array is equal to 1
if (probabilityArray[0] == 1) {
cout << "Probability Successful" << endl;
}
else {
cout << "Probability Failed" << endl;
}
}
int main() {
srand(time(0));
GetProbability(0, 100000, 100);
return 0;
}
};
It may give a StackOverflowException. To fix this, simply increase the 'Stack Reserve Size'.
EDIT:
After changing the code around a bit to return a 1 or a 0 based on the outcome, and putting it into a for loop which repeated itself 1000 times (I do NOT recommend trying this as it takes a while to complete), I got an output of 1, clearly showing that this piece of code works perfectly.

C++ Getting chamber to work for a Slot Machine program

The situation
Hey guys, so I'm working on a project right now. Basically I need to make a traditional slot machine, or fruit machine, or "one-armed bandit". It's a 3 x 1 x 3 character grid that changes whenever the user "pulls the lever"
I've done all of the code by myself from the top of my head as of right now, but I'm at an impasse and I wondered if you guys could possibly help.
I use the word "chamber", but think of that as being the word "Wheel" and only three of the values on the wheel are ever shown on the screen at any given time, so I called these "Blocks".
I'm trying to have a single chamber display output such as:
2
3
4
where I generated the random number of 3, and outputted 4 and 2 because they are adjacent on the chamber. This would be the start position of the chamber, which I can then manipulate.
Obviously, to get the random number converted and displayed on screen, I need to convert that integer to a char* which I'll need in the future for icons, which isn't great as I need to make a constant char.
I have two issues.
1) The first is, I call my spinChamer() method 3 times (because I have 3 chambers) but the random number generator in the method don't seem to make any difference to the output of the method, almost like there is a constant somewhere.
srand(time(NULL));
//generate start position for central block. use this to find upper and lower block.
int startpoint = rand() % 7 + 1;
2) The second is, to draw a string to a co-ordinate on the screen I have to convert to a char*. This involves converting my random int variable to a char* variable, which seems easy, however, when I try to add this converted value to the vector alongside it's upper and lower elements on the wheel, all 3 positions are the same value, when they shouldn't be, again, it seems like there is a constant somewhere that I'm missing.
for (int i = 0; i < 3; i++){
convert = std::to_string(startpoint + assigner);
temporarystore = (char*)convert.c_str();
blocks.push_back(temporarystore);
assigner++;
}
//spin around twice for visual effect.
for (int counter = 0; counter < 2; counter++){
Draw_String(drawY, drawX - 1, blocks.at(0));
Draw_String(drawY, drawX, blocks.at(1));
Draw_String(drawY, drawX + 1, blocks.at(2));
}
Any help would be greatly appreciated.
Note:
Draw_String() just draws the string to the screen, I won't edit that method due to dependencies elsewhere.
First issue: do not call srand(time(NULL)); inside the function that generates random numbers. Move it outside the function! srand() must be called only once during your program execution.
Second issue: It's not clear what you are trying to accomplish and why.
If you can use C++11 in your program, there is a new bunch of functions related to randomness.
#include <random>
#include <iostream>
namespace
{
std::random_device rd;
std::mt19937 mt(rd()); // seed the random number generator once
}
int GetRandomNumber(const int lowBound, const int highBound)
{
std::uniform_int_distribution<int> dist(lowBound, highBound);
return dist(mt);
}
int main()
{
const auto diceResult = GetRandomNumber(1, 6);
std::cout << diceResult << std::endl;
return 0;
}

error when i give sleep(1000), to make srand() work, in visual C++

i have following program:
srand((unsigned) time(NULL));
for (int w = 0; w < 10; w++) {
int ran_x;
ran_x = rand() % 255;
cout << "nRandom X = " << ran_x << endl;
//some more lines of code
Sleep(1000);
}
I am running it on visual c++ 2008, When I run this program, it doesnt show any errors or warnings. But when I run it, some of the times it runs fine, and some of the times it stops in the middle and gives this error "This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information."
What shall I do? Is it possible to do it with out using Sleep() function and still get randomly generated values. Because if I remove Sleep(1000), it doesnt give any error but it doesnt gives random values either
Obviously you shouldn't have to sleep. Code looks sane to me, as long as you only call srand() once. If you call this entire block of code multiple times intra-second, then time(NULL) will be returning the same second value and srand() will start the pseudo-random number generation at the same number, selecting the same set of 10 subsequent numbers....
Works without any problems with gcc
#include <iostream>
#include <cstdlib>
int main (int argc, char *argv[])
{
srand( time(0) );
for (int w = 0; w < 10; w++)
{
int ran_x = rand() % 255;
std::cout<<"\nRandom X = " << ran_x << std::endl;
sleep(1);
}
return 0;
}
Seems to me your program should work perfectly without the sleep call. In fact seems to work for me on VS2008 perfectly. I believe your problems must be in code that you have removed thinking it irrelevant.
The code snippet you posted is hardly responsible for your application terminating, Sleep or not.
Because if I remove Sleep(1000), it
doesnt give any error but it doesnt
gives random values either.
Well, rand() certainly gives you pseudo-random numbers, although the PRNG implementation might not return random values evenly distributed along the bits of the returned value, i.e. in many implementations, the higher bits are changing more often than the lower bits, which is why your code is a poor choice for selecting a random value between 0 and 255.
In general, I'd recommend switching from your standard library's rand/srand to an implementation like boost's mersenne twister (boost::random), or at least see
http://c-faq.com/lib/randrange.html
What's the content of "some more lines of code"?
<psychic debugging>I bet you have code that there that, directly or indirectly, depends on the random value you generated earlier. This code will likely be a division, or involve setting the length of some container, and borks when the generated random number is 0.</psychic debugging>

C++ random int function

Hello dear members of stackoverflow I've recently started learning C++, today I wrote a little game but my random function doesn't work properly. When I call my random function more than once it doesn't re-generate a number instead, it prints the same number over and over again. How can I solve this problem without using for loop?
Thanks
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
int rolld6();
int main()
{
cout<<rolld6()<<endl;
cout<<rolld6()<<endl;
system("PAUSE");
return 0;
}
int rolld6()
{
srand(time(NULL));
return rand() % 6 + 1;;
}
srand(time(NULL)); should usually be done once at the start of main() and never again.
The way you have it will give you the same number every time you call rolld6 in the same second, which could be a lot of times and, in your sample, is near guaranteed since you call it twice in quick succession.
Try this:
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <stdlib.h>
int rolld6 (void) {
return rand() % 6 + 1;
}
int main (void) {
srand (time (NULL));
std::cout << rolld6() << std::endl;
std::cout << rolld6() << std::endl;
system ("PAUSE");
return 0;
}
One other thing to keep in mind is if you run this program itself twice in quick succession. If the time hasn't changed, you'll get the same two numbers in both runs. That's only usually a problem when you have a script running the program multiple times and the program itself is short lived.
For example, if you took out your system() call and had a cmd.exe script which called it thrice, you might see something like:
1
5
1
5
1
5
It's not something you usually do but it should be kept in mind on the off chance that the scenario pops up.
You are constantly reseeding the random number generator. Only call srand(time(NULL)); once at the beginning of your program.
Random functions (no matter the language) are only partially random.
in every technology you will have a equivalent to
srand(time(NULL));
This piece of codes seeds the random function to a start value and then the numbers a generated from there onwards
this means if your always reseeding form the same value you'll always get the same numbers
In your case you want to do something like this (calling srand(time(NULL)); only once).
int rolld6 (void) {
return rand() % 6 + 1;;
}
int main (void) {
srand (time (NULL));
...
//call your function here
}
one of the advantage of seeding with the same value is to offer the possibility to regenerate the same sequence of random numbers.
in one of my games, I would randomly place objects on the screen, but I also wanted to implement a retry option. this options of reseeding from the same value allows me to redo it without storing all the random values ^^