5

Is it acceptable to use the C standard library's rand() function for random numbers that do not have to be cryptographically secure? If so, are there still better choices? If not, what should be used?

Of course, I assume the usual caveats about skew apply.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Gavin D. Howard
  • 371
  • 4
  • 9
  • 10
    You can use number `9` if it does not have to be secure. – Eugene Sh. Sep 23 '19 at 17:14
  • 1
    If you want "randomness" but don't care for cryptographically secure, then yes rand is fine. – Irelia Sep 23 '19 at 17:15
  • 7
    @EugeneSh. Obligatory Dilbert reference: https://dilbert.com/strip/2001-10-25 – dbush Sep 23 '19 at 17:20
  • @dbush Yeah, I suppose my choice was subconsciously affected by this strip – Eugene Sh. Sep 23 '19 at 17:21
  • 1
    [`4` should work as well.](https://xkcd.com/221/) – Patrick Roberts Sep 23 '19 at 17:22
  • 1
    This question lacks details and is unclear because it fails to state what the specifications are. It is like asking “Is a step stool acceptable if I do not need a 20-foot ladder?” The question does not contain enough information to know if a one-foot step stool is acceptable or you need a 10-foot ladder. – Eric Postpischil Sep 23 '19 at 19:23

4 Answers4

7

rand() suffers from some serious drawbacks.

  1. There is no guarantee on the quality of the random number. This will vary from implementation to implementation.
  2. The shared state used by different calls to rand, is not guaranteed to be thread safe.

As for POSIX C alternatives, there is random and random_r. OpenSSL provides more advances ways of generating random numbers.

The C++ (C++11 and later) library also provides a number of random number functions if including C++ in your project is an option.

doron
  • 27,972
  • 12
  • 65
  • 103
5

Cryptographic security aside, there are a lot of systems where rand() has pretty atrocious randomness properties, and the standard advice if you need something better is to use the non-Standard random().

rand's poor properties on many systems include:

  • nonrandomness in the low-order bits (such that e.g. rand()%2 is guaranteed to alternate 0,1,0,1...).
  • relatively short period, perhaps "only" 4 billion or so

So my (reluctant) advice is that if you need "good" randomness (say, for a Monte Carlo simulation), you may very well want to investigate using a nonstandard alternative to rand(). (One of my eternal questions about C is why any vendor would spend time deploying a nonstandard random() instead of simply making rand() better. And I do know the canonical answers, although they suck.)

See also this similar question.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
3

Yes, it is fine to use rand() to get pseudo-random numbers. In fact, that is the whole point of rand(). For simple tasks, where it is OK to be deterministic, you can even seed the system clock for simplicity.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • 4
    The “whole point” of `rand()` is indeed to get pseudo-random numbers, but it is notorious for having bad implementations and should not be recommended without caution. Even if the OP does not need cryptographic security, their needs might still be more than a bad `rand` implementation provides. Per the C 2018 standard, “There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits.” – Eric Postpischil Sep 23 '19 at 19:05
  • 1
    I accepted this as the answer since it directly answers the question. However, I encourage readers to consider all of the other answers as well. – Gavin D. Howard Sep 23 '19 at 19:05
  • @GavinHoward: Unfortunately, you accepted a bad answer when there are two others with better and more complete information. This answer is likely to lead people astray. – Eric Postpischil Sep 23 '19 at 19:07
  • @EricPostpischil as I said, for *simple* tasks `rand()` is often good enough. And furthermore, there is nothing inherently bad with `rand()`. Just like any other part of the standard library, it may have poor implementations. For any more complex tasks, there are surely better alternatives, but this specific question isn't about those. – Aykhan Hagverdili Sep 23 '19 at 19:13
  • 1
    @Ayxan: This answer lacks important information. And `rand` differs critically from most other routines in the standard library: They perform their functions even if their implementations are poor. For example, `strlen` may be slow, but it does not return a wrong answer. In contrast, the defects in `rand` can cause it to fail to serve its purpose. And it is notorious for poor implementations with such failures. – Eric Postpischil Sep 23 '19 at 19:25
3

The implementation of rand in mainstream C standard libraries may be adequate for casual use of pseudorandom numbers (such as in most single-player games, or for aesthetic purposes), especially if your application doesn't care about repeatable "randomness" across time or across computers. (But note that the rand specification in the C standard doesn't specify a particular distribution that the numbers delivered by rand have to follow.)

However, for more serious use of pseudorandom numbers, such as in a scientific simulation, I refer you to another answer of mine, where I explain that the problem with rand/srand is that rand

  • Uses an unspecified RNG algorithm, yet
  • allows that RNG to be initialized with srand for repeatable "randomness".

These two points, taken together, hamper the ability of implementations to improve on the RNG's implementation; changing that RNG will defeat the goal of repeatable "randomness", especially if an application upgrades to a newer version of the C runtime library by the same vendor or is compiled with library implementations by different vendors. The first point also means that no particular quality of pseudorandom numbers is guaranteed. Another problem is that srand allows for only relatively small seeds — namely those with the same size as an unsigned.

However, even if the application doesn't care about repeatable "randomness", the fact that rand specifies that it behaves by default as though srand(1) were called (and thus, in practice, generates the same pseudorandom sequence by default) makes using rand harder to use effectively than it could be.

A better approach for noncryptographic pseudorandom numbers is to use a PRNG library—

  • that uses self-contained PRNGs that maintain their own state (e.g., in a single struct) and don't touch global state, and
  • that implements a PRNG algorithm whose details are known to the application.

I list several examples of high-quality PRNG algorithms for noncryptographic pseudorandom numbers.

Peter O.
  • 32,158
  • 14
  • 82
  • 96