2

I want the random number generation to be controllable with a variable. For example, if I say 100, numbers should be generated with maximum randomness, and if I say 50, the numbers should not be 'as random'. If I say '0', possibly the random numbers should not be random at all - maybe all numbers generated are same.

Any idea what I can use to generate controlled random numbers like these? Any idea if some C++ inbuilt library, or maybe Boost library does this?

It will be good to have a way to regenerate the same sequence of random numbers, so a way to seed the generator would also be good.

Moeb
  • 10,527
  • 31
  • 84
  • 110
  • 9
    1) Study some probability theory so you know how to ask the right question; 2) look at the `` header for useful standard library functions. – Kerrek SB Oct 19 '12 at 03:01
  • Possibly relevant http://stackoverflow.com/q/2393899/10468 where I ask about introducing a controlled amount of correlations and about if a random series can be "too perfect" in randomness. – DarenW Oct 19 '12 at 04:07

6 Answers6

5

The way you describe your requirement seems to suggest that using a normal distribution (aka Gaussian distribution) may be the way to go. It has two parameters: Mean and standard deviation. If you set the standard deviation very low, you get random values that are probably quite close to the mean. If you set it to a large value, you get them distributed more widely.

In C++11 a normal distribution is available from the standard library. If C++11 is not an option for you, the Boost library has it, too.

Here is some example code:

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
#include <iomanip>

int main()
{
  std::random_device rd;
  std::mt19937 gen(rd());

  std::cout << std::fixed << std::setprecision(3);

  /* Mean 5, standard deviation very low (0.002): */
  std::normal_distribution<> d1(5,0.002);
  for (int i = 0 ; i < 20 ; ++i)
    std::cout << std::setw(7) << d1(gen) << "  ";
  std::cout << std::endl;

  /* Mean 5, standard deviation relatively high (2.0): */
  std::normal_distribution<> d2(5,2);
  for (int i = 0 ; i < 20 ; ++i)
    std::cout << std::setw(7) << d2(gen) << "  ";
  std::cout << std::endl;

  return 0;
}

Here is the output:

4.998    5.003    5.001    5.002    5.001    5.001    4.998    5.000    4.999    5.001    5.000    5.003    4.999    5.000    5.001    4.998    5.000    4.999    4.996    5.001  
2.781    3.795    5.669   -0.109    7.831    3.302    3.823    4.439    4.672    4.461    6.626    5.139    6.882    5.406    6.526    5.831    6.759    2.627    3.918    4.617

As you can see, in the first row all numbers are quite close to 5 (i.e., to use your wording, "randomness" is low), while in the second row the numbers are spread much more widely.

(EDIT: Of course, the randomness of these numbers isn't really affected. It's just that the standard deviation parameter makes the values more likely to emerge in a smaller (stddev low) or wider (stddev high) range of numbers.)

jogojapan
  • 68,383
  • 11
  • 101
  • 131
1

Boost has a library to do exactly what you want. Follow this link to the boost tutorial pages to teach you how to do numeric distributions.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
1

There is a point to this XKCD; you might want to meditate on it a while. There is really no such thing as "a random number", just as there is no such thing as "an uninteresting number".

What you can ask for is a series of numbers which satisfies some tests; for example, that in any subsequence, the frequency of each value will be roughly the same, or that there is no correlation between numbers and their successors in the sequence. These tests don't prove that the sequence is "random"; only that it is possibly representative of other such sequences; perhaps sequences which show up in the real world, unless constrained by un-, sub-, or super-natural forces.

In Rosencrantz and Guildenstern's simple sequence of coin flips, it's pretty easy to see that a biased distribution raises doubts, even existential ones. But suppose the coins flips had been completely balanced: heads, tails, heads, tails, heads, tails, heads, tails, and so through the Carpathian peaks. Would that be more or less random? As R (or G) says, "discuss".

rici
  • 234,347
  • 28
  • 237
  • 341
1

Start by generating a random sequence of bits.

When the knob is at 100, leave the sequence alone.

When the knob is at 50, force every other bit to be 1.

When the knob is at 0, force every bit to be 1.

[Update, to elaborate]

This suggestion is not as arbitrary as it probably sounds.

A truly random source of data has one bit of entropy per bit of data. If you want half that rate of entropy -- i.e., one bit of entropy per two bits of data -- you can just set every other bit to 1. If you want 1/3 that rate -- i.e., one bit of entropy per three bits of data -- you can just set every 2 out of three bits to 1. And so on.

"Bits of entropy per bit of data" is a perfectly reasonable definition for how random a sequence of numbers is... And to call a sequence "66% random" when 2 out of three bits are random while the others are fixed is a quite natural definition.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • Yes, this is a good answer (+1). Unlike my answer (which discusses how to generate _completely random_ sequences, but using a probability distribution that is increasingly non-uniform), this answer attempts to take the notion of _randomness_ seriously. – jogojapan Oct 19 '12 at 15:26
0

Probably the simplest solution is to use srand and rand in C++, both use pseudo-randomness, the larger the seed value in srand the more time it will take for a pattern to emerge in the random numbers generated by rand.

Edit:

http://www.cplusplus.com/reference/clibrary/cstdlib/srand/

0
r1 = Mathf.PingPong(Mathf.PerlinNoise(map,23)*5+map*.01, 1);

map is the random seed, an integer, ping-pong bounces all the values in between 0 and 1, Perlin noise makes some kind of noise which is evened out between 0 and 1 by adding a multiple of map to it.

bandybabboon
  • 2,210
  • 1
  • 23
  • 33