I somewhat understand the concept of the parentheses overload when you need to use an object as a function. The question that I have is why does the max variable in the listed code below always input 2.

/*
	Purpose: This is the header file of randomInteger.h
	The class creates a random integer
	Name: Saith
	Date: 3/5/11
	Edited: 5/28/11
*/

#ifndef RANDOMINTEGER_H
#define RANDOMINTEGER_H

#include<iostream>
using namespace std;

class randomInteger{
public:
	unsigned int operator() (unsigned int);
	unsigned time_seed();
};
#endif // RANDOMINTEGER_H
/*
	Purpose: This is the implementation file, randomInteger.cpp
	Name: Saith
	Date: 3/5/11
	Edited: 5/28/11
*/

#include<iostream>
#include<time.h>
#include"randominteger.h"

using namespace std;


unsigned int randomInteger::operator () (unsigned int max){
		// QUESTION: Why is Max always 2?  Or at least the times when I run/debug it.
unsigned int r; 
do{
		
     srand(time_seed());
     r = rand();						
	
 }while ( max < r);			// repeat while random number is greater than the maximum number.
	return r;
}

unsigned randomInteger::time_seed() {
    time_t now = time ( 0 );
    unsigned char *p = (unsigned char *)&now;
   unsigned seed = 0;
    size_t i;
  
    for ( i = 0; i < sizeof now; i++ )
      seed = seed * ( UCHAR_MAX + 2U ) + p[i];
 
   return seed;
}

It is used in the context as such:

void Deck::shuffle(){
	
	random_shuffle(deck, deck + topCard, randomizer);
}

Shuffle runs fine if I change the max value in the overload definition to 60, so it would read

while ( 60 < r);         // repeat while random number is greater than the maximum number.

I've tried:

random_shuffle(deck, deck + topCard, randomizer(topCard));

but that's a very improper way to using overloaded parentheses. Is there any way I can change this default through the shuffle function, or any other way? Also, topCard is local to the class Deck, deck is a dynamic array to the class Deck as well.


Note: Thanks Narue for a better understanding of rand(). Grabbed it from her site, Eternally Confused.

Dani AI

Generated

A short clarification and a practical modern fix.

What found — that the first call to the functor often sees max == 2 — is not a bug in the compiler or in rand(): it’s a consequence of which Fisher–Yates loop the library uses. Some implementations iterate forward and call the generator with i+1 where i starts at 1 (so the first bound passed is 2); others iterate backward and pass n. Both are valid. The important contract for the functor used by the old random_shuffle is simple: when called with argument n it must return a value uniformly in the range [0, n). That explains the observed sequence of bounds increasing from 2 upward.

A few practical notes that add to the earlier replies from and :

  • Do not call srand() inside the generator; seed once (or better, use a C++11 engine). Re-seeding per call resets the sequence and often produces repeated values.
  • Avoid rand()%n when high-quality uniformity is required; it introduces modulo bias unless handled carefully. Prefer the modern facilities in <random>.

A straightforward modern replacement (portable, faster, unbiased) is to stop using random_shuffle and use std::shuffle with a proper engine. Example pattern:

#include <algorithm>
#include <random>
#include <vector>

std::random_device rd;
std::mt19937 gen(rd());
std::shuffle(vec.begin(), vec.end(), gen);

If compatibility with the old random_shuffle API is necessary, implement a functor that wraps a std::mt19937 and uses std::uniform_int_distribution<std::ptrdiff_t>(0, n-1) inside operator()(std::ptrdiff_t n) so the returned value meets the [0,n) contract.

Final tip: when debugging, print the n values your functor receives — that quickly shows whether the algorithm is giving small bounds first (as observed) and removes uncertainty about where the “2” is coming from.

Recommended Answers

All 10 Replies

max is most likely 2, because you must be passing 2

Code presented is incomplete, so its hard to figure out why.

This morning I attempted to add a default constructor with one parameter, unsigned int, and a private member unsigned int max. I changed the

randomInteger randomizer;

to

randomInteger randomizer(topCard);

It compiled fine, but then I remembered after running it, the parameter in the overloaded parentheses function gets passed this max value; it does not need a private member variable for it. I suppose I can just remake the function so the overloaded parentheses operator does not need to be passed any values, or at least not use the value it was passed.

Below is a small, but complete program, that shows the same results that I was getting before.

/*
		Purpose: Recreate RandomInteger with a small test class
		Name: Saith
		Date: 5/29/11
*/

#include<iostream>
#include<algorithm>
#include"randomInteger.h"

using namespace std;

randomInteger randomizer;

int main(){

	int numbers [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

	random_shuffle(numbers, numbers + 10, randomizer);

	return 0;
}

The randomInteger .cpp and .h files are the exact same. I decided not to resubmit them to reduce the size of this message and spam effect.

ok, main calls random_shuffle,

where is the implementation of random_shuffle?

Again reading through the site that I just posted, the randomizer is suppose to get a value which is calculated by the pointer difference from the second parameter from the first in random_shuffle(para1, para2, para3). I'm trying to figure out why the pointer subtraction is not working correctly in both cases (My actual program and the newly made simple program).

First of all, you should only seed the random number generator once, not everytime you call rand(). So, you should seed the RNG in the constructor of randomInteger.

Second, to obtain a random number between 0 and some max-value, you can just use the modulus operator %. As so:

#ifndef RANDOMINTEGER_H
#define RANDOMINTEGER_H

#include<iostream>
using namespace std;

class randomInteger{
public:
        randomInteger();
	unsigned int operator() (unsigned int);
	unsigned time_seed();
};
#endif // RANDOMINTEGER_H

#include<iostream>
#include<time.h>
#include"randominteger.h"

using namespace std;

randomInteger::randomInteger() { 
  srand(time_seed()); 
};

unsigned int randomInteger::operator () (unsigned int max_value){
		// QUESTION: Why is Max always 2?  Or at least the times when I   run/debug it.
  return rand() % max_value;
}

unsigned randomInteger::time_seed() {
  time_t now = time ( 0 );
  unsigned char *p = (unsigned char *)&now;
  unsigned seed = 0;
  size_t i;
  
  for ( i = 0; i < sizeof(now); i++ )
    seed = seed * ( UCHAR_MAX + 2U ) + p[i];
 
  return seed;
}

Finally, I think your time_seed() function is much more complicated than it needs to be, but it should work still.

Okay. Ill agree with the srand() and making a default constructor with one parameters so it is not called once. Thisstill does not solve the fact of max being 2. You can completely delete srand() and just use rand(). And the max, value is still 2. Obviously the randomInteger class function should not have anything to do with random_shuffle(para1, para2, para3) call.


Either way, thanks for the input so far. Please keep them coming.

use a printf to print max and show result

similar to what you have, but max is not 2...

Also, personally, I would use a vector for input, less error prone...

#include <algorithm>
#include <ctime>

class MyRandom
{
public:
    ptrdiff_t operator() (ptrdiff_t max)
    {
        printf("max=%d-",(int)max);
        return rand()%max;
    }
};

int main () 
{
  srand ( unsigned ( time (NULL) ) );

  int numbers [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  int size = sizeof(numbers)/sizeof(int);

  MyRandom r;
  std::random_shuffle (numbers, numbers+size, r);

  return 0;
}

...I'm a fool.

I went out for a bike ride this afternoon and my mind wandered to this problem. I almost fell from the bike with laughter because I figured out what was happening.

I hadn't known the algorithm as well as I thought I did. Of course every time I run the program that it starts with 2. Once a "random" value is found, between 0 - 2, the max value is incremented to 3, then 4 all the way to the actual max value I was looking for. (Ironic, I've done plenty of sorting algorithms from scratch but this took me for a LOOP! Please excuse the pun).

The biggest reason why this wasn't so apparent to me at first was for the fact that my random numbers were always ranging from tens of thousands to high millions. It took quite a while for one to be as low as 0 through 2; that is when I decided to add the module (%) as Mike suggested.

Once it ran, I saw the incrementing of the max value. I feel foolish for not realizing this far ahead of time so as not to even come close to having this problem in the first place, but I bring this up for any other that may have had a lack of momentary sense as I did to find the answer they were looking for.

Thanks template<> and Mike_2000_17 for your input. I'll try to read an algorithm a little harder next time :D

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.