59

What is a good random number generator to use for a game in C++?

My considerations are:

  1. Lots of random numbers are needed, so speed is good.
  2. Players will always complain about random numbers, but I'd like to be able to point them to a reference that explains that I really did my job.
  3. Since this is a commercial project which I don't have much time for, it would be nice if the algorithm either a) was relatively easy to implement or b) had a good non-GPL implementation available.
  4. I'm already using rand() in quite a lot of places, so any other generator had better be good to justify all the changes it would require.

I don't know much about this subject, so the only alternative I could come up with is the Mersenne Twister; does it satisfy all these requirements? Is there anything else that's better?


Mersenne Twister seems to be the consensus choice. But what about point #4? Is it really that much better than rand()?

Let me be a little clearer on point 2: There is no way for players to cheat by knowing the random numbers. Period. I want it random enough that people (at least those who understand randomness) can't complain about it, but I'm not worried about predictions.

That's why I put speed as the top consideration.

Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
  • It does depend somewhat on what profile you want your random numbers to have; do you want them to be uniformly distributed? Gaussian? Discrete or continuous? – Stobor Jun 25 '09 at 23:44
  • 4
    Stobor, you can generate other distributions from uniform random numbers pretty well. – Joey Jun 25 '09 at 23:50
  • 3
    Yes, I know you can transform any type into any other type, but if you know you're primarily using the random variable in discrete binary decisions (true/false, left/right, etc) then you can increase speed by using a binary generator rather than using an integer one and calculating (x > RAND_MAX/2) every time. – Stobor Jun 25 '09 at 23:51
  • I'm hoping for a drop-in replacement for rand() (especially all those "rand() % 10" lines), so I'd prefer uniformly distributed and discrete. – Michael Myers Jun 25 '09 at 23:51
  • IF you suspect cheating, go with a crypographically random number generator... blizzard does it (see my answer below for link) – Ape-inago Jun 26 '09 at 00:31
  • On point 4: rand() is feeble in a number of ways, but only you can say whether it's currently "good enough" for what you're doing with it. – Steve Jessop Jun 26 '09 at 00:51
  • This doesn't contradict previous answers but does provide a bit of insight into why Mersenne Twister is highly regarded in C++: [A Proposal to Add an Extensible Random Number Facility to the Standard Library](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1452.html) Section H gives a rough overview of the pros and cons of more algorithms than you're ever likely to come across, and the whole paper addresses them from the perspective of a C++ programmer. – Kylotan Jun 26 '09 at 10:38
  • >Mersenne Twister seems to be the consensus choice. But what about point #4? Is it really that much better than rand()? Check http://ianbullard.squarespace.com/journal/2009/4/28/why-you-should-never-use-rand.html – sdcvvc Jul 30 '09 at 13:42
  • I used this class before and it is super-easy to use. [A Mersenne Twister Class](http://www.codeproject.com/KB/recipes/mersennetwisterclass.aspx) It is a class created from the original C code of the inventor of Mersenne Twister algorithm. – Khaled Alshaya Jun 26 '09 at 00:03
  • I've used the boost random libraries with games in the past. It has mercenne Twister http://www.boost.org/doc/libs/1_39_0/libs/random/index.html – Ryu Aug 04 '09 at 20:51
  • I haven't done a comparison in a long time, but here's a random collections of links, to other people's comparisons: * Universität Salzburg's pLab project * Dieharder: a random algorithm test suite * Wikipedia list of PRNGS (I'll pop back in with some more later...) – Stobor Jun 26 '09 at 00:11
  • If you're using the vim editor, you could just use the command `:%s/rand/newrand/g`, and it would replace every instance of 'rand' with the name of your new function. Not to mention most decent editors have a method for search/replace built-in. Last time I checked, even the Windows notepad had this feature. If the function takes parameters differently, you could always make a wrapper to minimize the amount of repetitive editing you have to do. – Braden Best Jan 02 '14 at 23:16
  • In addition, it's possible to redefine the constant RAND_MAX, if that helps at all. `#undef RAND_MAX` followed by `#define RAND_MAX [new max]` – Braden Best Jan 02 '14 at 23:21
  • Xorshit+ generates 64-bit random numbers and passes BigCrush: https://en.wikipedia.org/wiki/Xorshift#Xorshift.2B – Serge Rogatch Jun 16 '15 at 07:36
  • Here are three implementations of fast float random numbers generator you may find usefull: http://www.musicdsp.org/showone.php?id=273 – Delgan Oct 14 '16 at 09:50

25 Answers25

80

The other thread mentioned Marsaglia's xorshf generator, but no one posted the code.

static unsigned long x=123456789, y=362436069, z=521288629;

unsigned long xorshf96(void) {          //period 2^96-1
unsigned long t;
    x ^= x << 16;
    x ^= x >> 5;
    x ^= x << 1;

   t = x;
   x = y;
   y = z;
   z = t ^ x ^ y;

  return z;
}

I've used this one all over the place. The only place it failed was when I was trying to produce random binary matrices. Past about 95x95 matrices, it starts generating too few or too many singular matrices (I forget which). It's been shown that this generator is equivalent to a linear shift feedback register. But unless you are doing cryptography or serious monte carlo work, this generator rocks.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
AndyV
  • 809
  • 1
  • 7
  • 2
  • 1
    Numerical Recipes (I know, it's kind of debatable as they have put a lot of nonsense into those books over the years) advises against using XOR-shift alone and instead only in a combined generator. – Joey Nov 03 '09 at 06:42
  • 2
    too few singular matrices is how it should be, because singular matrices are "singular" in the space of all matrices. – a06e Feb 27 '14 at 16:29
  • 2
    What can be a 64-bit version without calling this function twice? Is it enough to replace with uint64_t and change the first shift from 16 to 32? – Serge Rogatch Jun 15 '15 at 15:03
  • 2
    Tried this and on my hardware/compiler it was slightly slower than the xorshift128 on the wikipedia page for xorshift. – Paul Brannan Sep 04 '15 at 16:48
  • 5
    While this is the accepted answer with many upvotes I have also found xorshift128 from Wikipedia page to be 2.5x times faster on skylake architecture. xorshf96 takes about 4.4ns on my system while xorshift128 takes about 1.4ns – Ody Nov 15 '19 at 19:10
  • 1
    How do you set x,y and z? – Hossein Feb 23 '21 at 03:54
  • I think you're missing a line with 1 space of indentation. – RobertR Aug 20 '22 at 00:45
44

Sometimes game developers don't want true randomness and a shuffle bag is more appropriate.

If you do want randomness, the Mersenne twister satisfies your requirements. It is fast, statistically random, has a long period and there are plenty of implementations out there.

Edit: rand() is typically implemented as a linear congruential generator. It's probably best if you make an informed choice of whether or not it's good enough for your purposes.

ZachB
  • 13,051
  • 4
  • 61
  • 89
David Johnstone
  • 24,300
  • 14
  • 68
  • 71
  • 5
    Spot on. Without this players will complain _constantly_ about things being too random. – toholio Jun 25 '09 at 23:42
  • I read that question already (in fact, it sparked the discussion that led to this question), but I don't think it is the solution. The "hits" here are abstracted away from the player, so players likely wouldn't even notice. – Michael Myers Jun 25 '09 at 23:48
  • "Empty body for-loops are Satan's offspring, but let's ignore this for now." +1 for a laugh and a good answer. (ironically, I used to use them alot in Perl...) – Matthew Scharley Jun 25 '09 at 23:49
38

There are much better choices than Mersenne Twister nowadays. Here is a RNG called WELL512, designed by the designers of Mersenne, developed 10 years later, and an all around better choice for games. The code is put in the public domain by Dr. Chris Lomont. He claims this implementation is 40% faster than Mersenne, does not suffer from poor diffusion and trapping when the state contains many 0 bits, and is clearly a lot simpler code. It has a period of 2^512; a PC takes over 10^100 years to cycle through the states, so it is large enough.

Here is a paper overviewing PRNGs where I found the WELL512 implementation. https://www.lomont.org/papers/2008/Lomont_PRNG_2008.pdf

So - faster, simpler, created by the same designers 10 years later, and produces better numbers than Mersenne. How can you go wrong? :)

UPDATE (11-18-14): Fixed error (changed 0xDA442D20UL to 0xDA442D24UL, as described in the paper linked above).

/* initialize state to random bits */
static unsigned long state[16];
/* init should also reset this to 0 */
static unsigned int index = 0;
/* return 32 bit random number */
unsigned long WELLRNG512(void)
   {
   unsigned long a, b, c, d;
   a = state[index];
   c = state[(index+13)&15];
   b = a^c^(a<<16)^(c<<15);
   c = state[(index+9)&15];
   c ^= (c>>11);
   a = state[index] = b^c;
   d = a^((a<<5)&0xDA442D24UL);
   index = (index + 15)&15;
   a = state[index];
   state[index] = a^b^d^(a<<2)^(b<<18)^(c<<28);
   return state[index];
   }
Nnnes
  • 213
  • 2
  • 8
Chris Lomont
  • 381
  • 2
  • 4
  • 4
    I waste one evening to understand why my code doesn't work: on 64 bit machines this code procude 64 bit number! Use `sizeof(unsigned long) * 8` – Ruggero Turra May 21 '10 at 20:58
  • 1
    @wiso, use `sizeof(unsigned long) * 8` instead of which part? – Shahbaz Apr 22 '13 at 08:44
  • 3
    The constant should be (according to original paper): 0xDA442D24UL – Mitch Wheat Apr 22 '13 at 08:48
  • 1
    @MitchWheat's comment is correct: 0xDA442D20UL should be 0xDA442D24UL. (I tried to edit this over a year ago, but for some reason it was rejected.) This problematic version was given in the Lomont_PRNG_2008.pdf paper linked above, then later corrected (see History section at the end of the paper). But the code here still shows the incorrect version. The original implementation by the WELL creators, for comparison, is here: http://www.iro.umontreal.ca/~panneton/well/WELL512a.c (Note that this change is tiny, but these things can have a huge impact on random generator algorithms.) – Tyler Streeter Sep 27 '14 at 18:04
  • @Shahbaz (and others that may read this): I think he means that users of this code should check the result of sizeof(unsigned long)*8 on their machine/compiler... If the result is 64 (i.e. unsigned longs are 64 bits wide), then this code will produce unexpected results because it assumes unsigned longs are 32 bits wide. Compare the original implementation here, which uses unsigned ints instead of unsigned longs: http://www.iro.umontreal.ca/~panneton/well/WELL512a.c – Tyler Streeter Nov 18 '14 at 19:25
  • @TylerStreeter, I'm not saying anything against your comment, but you don't need `sizeof(unsigned long)*8` to check for 64-bit, you can just check `sizeof(unsigned long)` (Of course, assuming `char` is 8 bits). So either there is another reason for @RuggeroTurra's comment, or he was not paying much attention. – Shahbaz Nov 19 '14 at 09:50
  • @Shahbaz: Sure, of course the *8 is unnecessary. I'm guessing the purpose of his comment was simply to state that unsigned longs have different sizes (e.g. 4 vs. 8 bytes) on different platforms, and that the code listed here is problematic because it assumes unsigned longs are 4 bytes. (So users of this code should probably change the unsigned longs e.g. to uint32_t.) – Tyler Streeter Nov 19 '14 at 14:05
  • `a PC takes over 10^100 years to cycle through the states` is 2008 claim (from the paper), and really vague. Can you please specify better the speed estimation? – Marek Sebera Feb 15 '15 at 18:05
33

Two good alternatives from intel's site:

1) fastrand - it is 2.01 X faster than the std rand(). The routine returns one integer, similar output value range as C lib.

inline int fastrand() { 
  g_seed = (214013*g_seed+2531011); 
  return (g_seed>>16)&0x7FFF; 
} 

2) an SSE version (see link below) is about 5.5 X as fast as std rand() however it generates 4 random values at a time, requires a processer with sse (almost all do), and is more complicated.

http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/

Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
Sunsetquest
  • 339
  • 3
  • 2
29

George Marsaglia has developed some of the best and fastest RNGs currently available Multiply-with-carry being a notable one for a uniform distribution.

=== Update 2018-09-12 ===

For my own work I'm now using Xoshiro256**, which is a sort of evolution/update on Marsaglia's XorShift.

=== Update 2021-02-23 ===

In .NET 6 (currently in preview) the implementation of System.Random has been changed to use xoshiro256**, but only for the parameterless constructor. The constructor that takes a seed uses the old PRNG in order to maintain backwards compatibility. For more info see Improve Random (performance, APIs, ...)

redcalx
  • 8,177
  • 4
  • 56
  • 105
  • 1
    It was seeing Marsaglia's criticism in the Wikipedia article on Mersenne Twister that actually made me ask this question. Does anyone actually use these, though? – Michael Myers Jun 27 '09 at 03:47
  • Not sure how widespread use of these is but I used Marsaglia's xor-shift RNG in my pet project and released the RNG as: http://www.codeproject.com/KB/cs/fastrandom.aspx Subsequently this code was ued in a RNG code library: http://www.codeproject.com/KB/recipes/Random.aspx And I also was asked to modify the licensing for it to be used in some project at Novell running on Mono. – redcalx Jun 29 '09 at 08:34
  • I accepted this because in my simple tests, the XOR-shift generator proposed by Marsaglia was by a fair margin the fastest of the competitors. I will also consider switching to WELL512 at some point; I've abstracted all calls to `rand` into an encapsulating class so it's very easy to change the implementation. – Michael Myers Aug 04 '09 at 23:58
  • Thanks, I chose it for speed also, while it also passes Marsaglia's suite of RNG tests. Another benefit is that the seed can be reset quickly, whereas other RNGs require an initialisation routine to be run on settign the seed. This is a useful feature if you need to re-generate the exact same sequence of numbers (start with the same seed) and need to switch the seed frequently. – redcalx Aug 05 '09 at 10:37
12

See these generators from random number generator expert George Marsaglia. They're implemented as C macros, and they're lightning fast, just a few operations per number generated.

John D. Cook
  • 29,517
  • 10
  • 67
  • 94
11

Buy a cheap webcamera, a ionizing smoke detector. Disassemble both of them, smoke detector contain little radioactive material - a source of gamma waves - which will result in firing photons at your webcamera. That's your source of true randomness :)

Vexatus
  • 880
  • 1
  • 7
  • 11
  • 1
    Again, I don't really care about true randomness. I just want it pretty close and pretty fast. – Michael Myers Jun 26 '09 at 13:04
  • 2
    This idea generates events at random times, but not random bits on demand. Plus the smoke-detector-webcam hardware is going to be seen as a copy-protection dongle by the customer base. – Jeff Sharp Jul 30 '09 at 14:02
  • 3
    I'd buy the game just because it has a "copy-protection" dongle with a radioactive warning sticker on it! – Grant Peters Aug 04 '09 at 00:57
10

Mersenne Twister is typical in the industry, especially since it lends itself well to SIMD and can be made super fast. Knuth is popular too (thanks, David).

In most game applications speed is really the critical factor, since players are going to complain about low framerate a lot more than they will complain about the fact that there is a slight bias towards generating a 3 whenever it is preceded by a 7, 2, and 9 in that order.

The exception of course is gambling for money, but there your relevant licensing authority will specifically lay out the algorithms that you can use.

Crashworks
  • 40,496
  • 12
  • 101
  • 170
  • 3
    They may complain alot (and fairly loudly) that the 3 never seems to come up at all for them. Depends on the usage. True random is good for things like damage, but for things like item drops it makes sense to use a shuffling algorithm like @David Johnstone posted. – Matthew Scharley Jun 25 '09 at 23:57
  • True enough; you'll want a different algorithm depending on whether "fairness" or true randomness is more important. – Crashworks Jun 26 '09 at 00:03
  • They don't get to actually see the random numbers, but they do notice that sometimes they lose when they don't expect to. (I'm sure it happens the other way too, but they hardly ever seem to notice it.) Perhaps a normal distribution would be better for the combat part. – Michael Myers Jun 26 '09 at 00:04
  • Also, most languages have a good off-the-shelf implementation of MT available, and probably one under a licence that doesn't preclude you from incorporating it in commercial software. – ConcernedOfTunbridgeWells Jun 26 '09 at 10:31
8

Starting with Ivy Bridge architecture Intel added RdRand CPU instruction and AMD added it later in June 2015. So if you are targeting a processor that is new enough and don't mind using (inline) assembly, the fastest way to generate random numbers should be in calling RdRand CPU instruction to get a 16- or 32- or 64-bit random number as described here. Scroll to approximately the middle of the page for code examples. At that link there is also a code example for checking the current CPU for support of RdRand instruction, and see also the Wikipedia for an explanation of how to do this with the CPUID instruction.

Related question: Making use of sandy bridge's hardware true random number generator? (though according to Wikipedia, RdRand instruction first appeared in Ivy Bridge, but not Sandy Bridge architecture as that question says)

Example C++ code based on _rdrand64_step() :

#include <immintrin.h>

uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
  // Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number
Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158
  • 3
    `rdrand` is actually slow. See 3.4.1 of https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide and https://stackoverflow.com/questions/10484164/what-is-the-latency-and-throughput-of-the-rdrand-instruction-on-ivy-bridge. In a quick benchmark, `xorshift128` clocks about 13x faster than `rdrand32`. Intel claims 70 - 200 MB/s/thread continuous. – ZachB Mar 13 '18 at 04:36
6

Mersenne Twister is very good, and it's fast as well. I used it in a game and it's not hard at all to implement or use.

The WELL random algorithm was designed as an improvement over the Mersenne Twister. Game Gems 7 has more info. on it, if you can borrow that or have it.

On that WELL page I linked you to, the number is the period of the algorithm. That is, you can get 2^N - 1 numbers before it needs reseeding, where N is: 512, 1024, 19937, or 44497. Mersenne Twister has a period of N = 19937, or 2^19937 - 1. You'll see this is a very large number :)

The only other thing I can point out is that boost has a random library, which you should find useful.

In response to your edit, yes the Twister or WELL is that much better than rand(). Also, the old modulus trick harms the distribution of the numbers. Even more reason to use boost :)

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 1
    Is boost worth it just for random numbers? We aren't using it at all right now. – Michael Myers Jun 25 '09 at 23:55
  • Boost is very worth it. Clean C++ use (just check out the page), along with all the other things boost offers, like smart pointers, boost::functions, lambda's, threads, etc... I basically treat boost like the STL. Once it's set up, which isn't too difficult, you'll be able to forget it's even there, and be glad when you do need it. – GManNickG Jun 25 '09 at 23:58
  • 2
    Remember that boost is not either or. You just include the single header file you need, and that is all you get. Most boost libraries is even header-only libraries, so no need to link to anything, everything is in the header file. – Bjarke Freund-Hansen Jul 13 '09 at 17:23
5

The Mersenne Twister has some fast implementations.

lhf
  • 70,581
  • 9
  • 108
  • 149
  • 1
    MT19937 is usually faster than an LCG. Also there is the SIMD-oriented Fast Mersenne Twister: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html which is even faster. – Joey Oct 30 '09 at 06:59
  • Mersenne Twister is a poor choice https://arxiv.org/abs/1910.06437 – WarmupBallad Nov 04 '21 at 21:52
4

In a real-time game, there's no way for a player to determine the difference between a "good" generator and a "bad" one. In a turn-based game, you're right--some minority of zealots will complain. They'll even tell you stories, in excruciating detail, of how you ruined their lives with a bad random number generator.

If you need a bunch of genuine random numbers (and you're an online game), you can get some at Random.org. Use them for turn-based games, or as seeds for real-time games.

Nosredna
  • 83,000
  • 15
  • 95
  • 122
  • It's semi-real-time. For example, in combats, the "dice" are re-rolled every 5 game days. Combats generally last a game month or more, though. – Michael Myers Jun 26 '09 at 00:05
  • Oh, and it's not web-based, so random.org isn't an option. – Michael Myers Jun 26 '09 at 00:11
  • It's totally possible to experience true-random frustration in a real-time game. If, every time you hit the "attack" button, your sword misses the giant rat, you will be just as pissed as if you had to spend a "turn" on every miss. – ojrac Jun 26 '09 at 00:18
  • @ojrac. That's true, you can experience it. What I meant is that a user can't identify the random numbers coming at him. But you're correct that the player often doesn't want true random numbers. He wants fun numbers, which may have an entirely different distribution. But the programmer can solve that problem by post-processing "real" random numbers into different sequences or distributions. – Nosredna Jun 26 '09 at 00:42
  • random.org still might be a choice even if your game is not web based. If you require any kind of internet connection, you can either connect to the random.org on demand or you can request a long list of random numbers in a spesified range, store them and use as needed. If you run out of pre-fetched randoms, you can fall back to good-old rand(). One last note: random.org uses the static noise from the sound input so you may try to use that also as random seed. – BYK Jul 30 '09 at 09:00
4

I'm a fan of Isaac, unlike mersense twister, it's crypographically secure (you *can't crack the period by observing the rolls)

IBAA (rc4?) is also one that is used by blizzard to prevent people from predicting the random number used for loot rolls.. I imagine something similar is done w/ diablo II when you are playing off of a battle.net server.

*can't within any reasonable timeframe (centuries?)

Ape-inago
  • 1,870
  • 1
  • 13
  • 27
4

Even tho this post is years old, it showed up when I was looking for a similar answer, and the answer I wound up using, isnt even in it. So I'm adding the one I found;

#include <random> msdn entry

This approach will build a self contained random generator, and I found it to be a lot more random than rand()%x; over a few hundred thousand iterations. rand()% would never throw 16+ heads/tails in a row, when it should every other 65k attempts. This one not only does that, but it does it in a quarter of the time.

This is how I implement #include <random> myself:

//create rng_gen, using mt technique, with range 0,1 (coin) and 1,6(dice);
std::random_device rd; //seed
std::mt19937 gen(rd()); //seed for rd(Mersenne twister)
std::uniform_int_distribution<> rng_coin(0, 1); //rng1 range
std::uniform_int_distribution<> rng_dice(1, 6); ///rng2 range

rng_coin(gen); //will apply rng1 range on (gen) object. Is very fast
rng_dice(gen); //will apply rng2 range, returns int.

//will output 1000 cointosses to console
for (int i=0;i<1000;++i)std::cout<<rng_coin(gen)<<"\n";
//will generate 1000 dice throws
for (int i=0;i<1000;++i)rng_dice(gen);
ovanes
  • 5,483
  • 2
  • 34
  • 60
Charlie
  • 585
  • 9
  • 17
3

Based on the random number generator by Ian C. Bullard:

// utils.hpp
namespace utils {
    void srand(unsigned int seed);
    void srand();
    unsigned int rand();
}

// utils.cpp
#include "utils.hpp"
#include <time.h>

namespace {
    static unsigned int s_rand_high = 1;
    static unsigned int s_rand_low = 1 ^ 0x49616E42;
}

void utils::srand(unsigned int seed)
{
    s_rand_high = seed;
    s_rand_low = seed ^ 0x49616E42;
}

void utils::srand()
{
    utils::srand(static_cast<unsigned int>(time(0)));
}

unsigned int utils::rand()
{
    static const int shift = sizeof(int) / 2;
    s_rand_high = (s_rand_high >> shift) + (s_rand_high << shift);
    s_rand_high += s_rand_low;
    s_rand_low += s_rand_high;
    return s_rand_high;
}

Why?

  • very, very fast
  • higher entropy than most standard rand() implementations
  • easy to understand
Armin Ronacher
  • 31,998
  • 13
  • 65
  • 69
  • 1
    Ian has an interesting article that compares several generators. http://ianbullard.squarespace.com/journal/2009/4/28/why-you-should-never-use-rand.html – Sean McCauliff Jul 31 '09 at 20:55
  • Is it supposed that by giving it a seed that differs only slightly you only get slightly different results? – API-Beast Feb 17 '14 at 05:46
2

An additional criteria you should consider is thread safety. (And you should be using threads in todays multi-core environments.) Just calling rand from more than one thread can mess with it's deterministic behavior (if your game depends on that). At the very least I'd recommend you switch to rand_r.

geowar
  • 4,397
  • 1
  • 28
  • 24
2

Boost library has a set of random generators. Performance chart could be found here.

EDIT: This answer was here before the edit of the original question. But I hope it could be still helpful, so I leave it here.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • 1
    updated chart http://www.boost.org/doc/libs/1_47_0/doc/html/boost_random/reference.html#boost_random.reference.generators – k107 Sep 19 '11 at 23:15
1

GameRand implement the algorithm posted here http://www.flipcode.com/archives/07-15-2002.shtml

This is something I originally developed in the late 80s. It easily beat rand() in term of numerical quality, and as the side benefit to be the fastest random algorithm possible.

sschaem
  • 11
  • 1
1

I'd vote for the Mersenne Twister as well. Implementations are widely available, it has a very large period of 2^19937 -1, is reasonably fast and passes most randomness tests including the Diehard tests developed by Marsaglia. rand() and Co., being LCGs, produce lower quality deviates and their successive values can be easily inferred.

One point of note, however, is to properly seed MT into a state that passes randomness tests. Usually a LCG like drand48() is used for that purpose.

I'd say the MT satisfies all the requirements you've set (provably), and it'd be an overkill to go for something like MWCG imo.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
1

can you pregenerate a bunch of random bits ahead of time and peel them off 2 at a time (since you only need a random number between 1 and 3)?

Mikeb
  • 6,271
  • 3
  • 27
  • 41
0

I want it random enough that people (at least those who understand randomness) can't complain about it, but I'm not worried about predictions.

A-ha!

There's your real requirement!

No one could fault you for using Mersenne Twister in this application.

Marsh Ray
  • 2,827
  • 21
  • 20
0

Depending on the target OS, you might be able to use /dev/random. It doesn't really require any implementation, and on Linux (and maybe some other operating systems) it's truly random. The read blocks until sufficient entropy is available, so you might want to read the file and store it in a buffer or something using another thread. If you can't use a blocking read call, you can use /dev/urandom. It generates random data almost as well as /dev/random, but it reuses some random data to give output instantly. It's not as secure, but it could work fine depending on what you plan to do with it.

nonpolynomial237
  • 2,109
  • 4
  • 27
  • 35
0

I think WELL is pretty good, and WELL512a is pretty short. http://www.iro.umontreal.ca/~panneton/WELLRNG.html WELL44497a is complex at the time too. However, WELL generates a number between 0 and 1.

0

You know what? Forgive me if you think this answer completely sucks... But I've been (for god only knows what reason...) using DateTime.Now.Milliseconds as a way to get a random number. I know it's not completely random, but it appears to be...

I just couldn't be bothered typing so much JUST to get a random number! :P

jay_t55
  • 11,362
  • 28
  • 103
  • 174
  • 3
    Speed matters a lot to OP, so it'll probably be called very frequently, so could easily get the same milliseconds values many times. Anyway sampling time repeatedly, especially in fixed-speed loops as typical in a game, would behave very non-randomly. – Beni Cherniavsky-Paskin Aug 30 '13 at 08:13
-3

rand() is really darn fast, and I don't believe you'll find much faster.

If it is in fact slowing you down (which I kinda doubt), then you need an architecture change.

I recommend pre-populating a long list with random numbers, then when you need one, simply take one from the list, rather than generating one. You may be able to re-fill the list with a background thread.

abelenky
  • 63,815
  • 23
  • 109
  • 159
  • 12
    On modern processors it is faster to calculate new numbers than to pull one from memory. – Mark Ransom Sep 16 '11 at 18:48
  • 1
    I tried this and it was by far the fastest method on Tegra3, if you iterate over the array in sequential order after populating it. Downside is that numbers will be repeating with a short period. – Learn OpenGL ES Aug 10 '13 at 15:18
  • 2
    Quite an old reaction, but @MarkRansom: you're sure about that? Having a dense list (which enables caching and prefetching improvements) of random numbers should be much much faster than any sufficiently good random number generation. Or do you have any code showing otherwise? – Bouncner Jun 25 '17 at 11:46
  • xor_shift gens are approx 6-10x faster than rand() – metamorphosis Dec 08 '20 at 00:22
  • At the end of day. Measure and do not simply trust what you have been told. What may be great at processor A maybe suboptimal at processor B. – rxantos Jan 20 '22 at 23:57