5

I was wondering how to generate random unsigned char values. My idea;
rand()%255; since unsigned chars support between 0-255. I was wondering if this method could be improved(or is it the most legit way to do this)

Ali
  • 5,338
  • 12
  • 55
  • 78
  • 4
    Define "improve". BTW you should use `rand()%256`. – mfontanini Apr 03 '12 at 23:56
  • Actually I should edit "improve" I was wondering if this was the right way – Ali Apr 03 '12 at 23:58
  • It is the right way. You could also use the random utilities provided in C++11, but this works. – mfontanini Apr 03 '12 at 23:58
  • 1
    It also depends on what you intend to use these values for. Are they going to be used as characters (e.g. to form a string that you are going to print or perform other string operations on)? Or are you using them just as an unsigned 8-bit integer? – Raymond Chen Apr 04 '12 at 00:01
  • I'm running the function in a loop to fill a matrix and most of the signs are "?". I've set the srand as 'srand((unsigned)time(NULL));' – Ali Apr 04 '12 at 00:10
  • @rolandbishop : I hope you're not calling `srand` inside the loop... – ildjarn Apr 04 '12 at 00:14
  • Course not, just one time at the very beginning of the program – Ali Apr 04 '12 at 00:16
  • Just a note: 0-255 are 256 values, so you probably want `rand() % 256` [or `rand() & 0xFF`]. – Daniel Fischer Apr 04 '12 at 00:40

5 Answers5

6

A lot faster will be simple

unsigned char a = (unsigned char) rand();

Or you can do even 4 shifts of generated integer (on 32bit architecture) to four times reduce call to rand():

int a = rand();
unsigned char r1 = (unsigned char) a;
unsigned char r2 = (unsigned char) a >> 8;
unsigned char r3 = (unsigned char) a >> 16;
unsigned char r4 = (unsigned char) a >> 24;

Or something like that.

Petr Újezdský
  • 1,233
  • 12
  • 13
  • since (unsigned char) up there, rand() function won't be going off limits right? – Ali Apr 04 '12 at 00:06
  • 8
    On platforms for which `RAND_MAX` is less than `INT_MAX` (e.g. VC++ where `RAND_MAX` is `32767`), the high-order bytes will always be `0`. – ildjarn Apr 04 '12 at 00:06
  • The point still comes across. A simple check of whether this is the case beforehand would do the trick. – chris Apr 04 '12 at 01:16
5

The C++11 random number library is the best way if you want to stick to the standard library:

#include <random>

#include <functional>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <climits>

int main() {
    std::random_device r;
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};

    auto rand = std::bind(std::uniform_int_distribution<>(0, UCHAR_MAX),
                          std::mt19937(seed));

    std::generate_n(std::ostream_iterator<int>(std::cout," "), 25, rand);
}

The library provides some uniform random number engines and adapters to use with them to produce various distributions. Here we use a mt19937 engine (seeded using random_device (as a source of non-deterministic data if possible), and seed_seq to combine enough random data into a form suitable for filling out mt19937's internal state. Then we adapt the mt19937 using a uniform_int_distribution. By default this distribution will produce numbers uniformly distributed across the range supported by its template parameter, in this case unsigned char. So the function object we create will produce values in the range [0 256). Its results are demonstrated by writing out 25 values to the standard output.

There are distributions for other uses such as producing a normal distribution, simulating coin flips, or picking items out of a set with arbitrary weights (e.g. picking one of 3 items where the first is picked 50% of the time, the second is picked 10% of the time, and the third, 40% of the time).

Other engines are provided for different quality and performance characteristics. For example if you need a cryptographic random number generator, random_device may provide it if your implementation offers such capability.


Some additional resources.

bames53
  • 86,085
  • 15
  • 179
  • 244
2

A slightly cleaner way to do this the C++ way, using the random library would be:

#include <random>

int myseed = 1234;

std::default_random_engine rng(myseed);
std::uniform_int_distribution<int> rng_dist(0, 255);
char mychar = static_cast<unsigned char>(rng_dist(rng));
Riot
  • 15,723
  • 4
  • 60
  • 67
1

You could use unsigned char n = (unsigned char)(rand() & 0x00ff);

John3136
  • 28,809
  • 4
  • 51
  • 69
0

And you should be aware that rand() is one of the worst of the widely available random number generators, in terms of the quality (randomness) of its output. On UNIX-based systems, and some others, random() and lrand48() [and friends] are substantially better. For speed, the best way to use these is as described by @Pida, above, where you call only once for a word's worth of random bits. The word size depends on the random number generator you use.

DRVic
  • 2,481
  • 1
  • 15
  • 22