2
float genData(int low, int high);
    
int main(){
    srand(time(0)); 
    float num = genData(40, 100);
    cout << fixed << left << setprecision(2) << num << endl;
            return 0;
}
        
float genData(int low, int high) {
    low *= 100;
    high *= 100 + 1;
    int rnd = rand() % (high - low) + low;
    float newRand;
    newRand = (float) rnd / 100;
    return newRand;
}

I'm expecting a random number between 40 and 100 inclusively with two decimal places. eg: 69.69, 42.00

What I get is the same number with different decimal values, slowly increasing every time I run the program.

  • @Chris I have in the main function, is that not good enough? –  Oct 22 '21 at 00:59
  • @phuclv I have a prototype, its on the first line. –  Oct 22 '21 at 01:03
  • 1
    C++ provides [Pseudo-random number generation](https://en.cppreference.com/w/cpp/numeric/random) (see example on page) See also [std::uniform_int_distribution](https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution) and [std::uniform_real_distribution](https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution) – David C. Rankin Oct 22 '21 at 01:04
  • 4
    at first glance I can't spot anything wrong with your code. It could be the quality of `rand`. Use C++11 random library instead. – bolov Oct 22 '21 at 01:12
  • 1
    @t1231 sorry, I glossed over that. What platform are you on? Many have notoriously bad `rand` implementation like [the one in macOS](https://stackoverflow.com/q/7866754/995714) – phuclv Oct 22 '21 at 01:15
  • https://ideone.com/QvsnxX some random linux is fine. so i guess this is an environment issue what libc do you use? – Volodymyr Boiko Oct 22 '21 at 01:18
  • I am on windows 10 using Clion –  Oct 22 '21 at 01:19
  • @BarmakShemirani where would I use another rand()? –  Oct 22 '21 at 01:25
  • @BarmakShemirani my problem is solved, thank you!! –  Oct 22 '21 at 01:30
  • You also have additional range problem, see the answers. – Barmak Shemirani Oct 22 '21 at 01:33
  • "What I get is the same number with different decimal values, slowly increasing every time I run the program." is an artifact of 1) Using `time()` to initialize 2) a terrible `srand()/rand()` implementation. – chux - Reinstate Monica Oct 22 '21 at 20:03

3 Answers3

4

Use the <random> header for that:

#include <iostream>
#include <random>

float getData(int const low, int const high) {
  thread_local auto engine = std::mt19937{ std::random_device{}() };

  auto dist = std::uniform_int_distribution<int>{ low * 100, high * 100 };

  return dist(engine) / 100.0f;
}

int main() {
  for (auto i = 0; i != 5; ++i) {
    std::cout << getData(40, 100) << '\n';
  }
}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • Note: `uniform_real_distribution(a,b)` is a uniformly distributed on the interval [a, b). 100.00 is not generated so almost meets "random number between 40 and 100 inclusively". Likely close enough for OP's needs it the result is rounded to nearest 0.01 per the usual `float` limitaitons. – chux - Reinstate Monica Oct 22 '21 at 01:19
  • @chux-ReinstateMonica See if this one is better – Aykhan Hagverdili Oct 22 '21 at 01:23
  • Ayxan, It comes down to "random number between 40 and 100 inclusively with two decimal places", that is 6001 different values and how close to that OP really wants. This answer (low, high) or (low,next(high)) both 1) get many values between the xx.xx values and 2 ) With a rounded to nearest 0.01, do not get the end values with same uniformity as the others. Of course 2 decimal place values are not truly possible with `float`. – chux - Reinstate Monica Oct 22 '21 at 01:39
  • @chux-ReinstateMonica I see what you mean. Thank you for the feedback. Please see if this update is better. – Aykhan Hagverdili Oct 22 '21 at 01:44
  • Maybe `high * 100` --> `high * 100 + 1` to catch 100.00? – chux - Reinstate Monica Oct 22 '21 at 01:45
  • @chux-ReinstateMonica for [uniform_int_distribution](https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution) the range is always inclusive because otherwise how would you get INT_MAX or ULLONG_MAX – Aykhan Hagverdili Oct 22 '21 at 01:47
  • Hmm: [not upper inclusive](https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution), [upper inclusive](https://www.cplusplus.com/reference/random/uniform_int_distribution/). I'll have to dig up the C++ spec. – chux - Reinstate Monica Oct 22 '21 at 01:51
  • 1
    @chux-ReinstateMonica *real* version is not inclusive, *int* version is inclusive. – Aykhan Hagverdili Oct 22 '21 at 01:52
  • Ayxan [Yes](http://www.quickmeme.com/meme/3twuvz). LSNED "A `uniform_int_distribution` random number distribution produces random integers i, a <= i <= b, distributed according to the constant discrete probability function" C++ 26.5.8.2.1. – chux - Reinstate Monica Oct 22 '21 at 01:54
3

Wrong range

int rnd = rand() % (high - low) + low; does not generate the right range.

float genData(int low, int high) {
  low *= 100;
  // high *= 100 + 1;
  high = high*100 + 1;

expecting a random number between 40 and 100 inclusively with two decimal places. eg: 69.69, 42.00

That is [40.00 ... 100.00] or 10000-4000+1 different values

int rnd = rand() % (100*(high - low) + 1) + low*100;
float frnd = rnd/100.0f; 

rand() weak here when RAND_MAX is small

With RAND_MAX == 32767, int rnd = rand() % (high - low) + low; is like [0... 32767] % 6001 + 40000. [0... 32767] % 6001 does not provide a very uniform distribution. Some values coming up 6 times and others 7-ish.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

If you are using C++ 11 you can use better random number generators that will give you diversity in the generated numbers in addition to being a lot faster.

Quick Example:

#include <random> // The header for the generators.
#include <ctime> // To seed the generator.
 
// Generating random numbers with C++11's random requires an engine and a distribution.
mt19937_64 rng(seed);
// For instance, we will create a uniform distribution for integers in the (low, high) range:
uniform_int_distribution<int> unii(low, high);
// Show the random number
cout << unii(rng) << ' ';

You can follow this article for more explanation from here.

Mostafa Wael
  • 2,750
  • 1
  • 21
  • 23
  • Considering the question asks for a " number with two decimal places", `uniform_int_distribution` on its own is insufficient. But throw in a `/100.0` and you get two decimal places out. Of course, that will also require a `*100` for the range. – MSalters Oct 22 '21 at 12:43
  • Yes, you are right, I was showing how can he get a better random number then, he can do any needed processing. Thanks for your note. – Mostafa Wael Oct 22 '21 at 15:01