C++ numerics lib: std::uniform_int_distribution, change bounds of distribution between calls
What about param
?
dist.param( decltype(dist)::param_type(otherMin, otherMax) );
C++11 standard (and following ones), [rand.req.dist]/9:
For each of the constructors of
D
taking arguments corresponding to
parameters of the distribution,P
shall have a corresponding
constructor subject to the same requirements and taking arguments
identical in number, type, and default values.
Problems with uniform_int_distribution
This error is consistent with you leaving off std::
, so you should use it like follows:
std::uniform_int_distribution<> dis(0,5);
See it working live.
Note as WhozCraig mentioned you also need to include the random header:
#include <random>
bernoulli_distribution vs uniform_int_distribution
Some comments and answers suggest using uniform_real_distribution
instead.
I tested uniform_real_distribution(0.0f, nextafter(1.0f, 20.f))
(to account for urd
being a half-closed range) vs bernoulli_distribution
and the bernoulli_distribution
is faster by about 20%-25% regardless of the probability (and gave more correct results. I tested 1.0
true probability and my implementation that used the above urd
values actually gave false negatives (granted one or two out of 5 one-million runs) and bernoulli
gave the correct none.
So, speed-wise: bernoulli_distribution
is faster than uniform_real_distribution
but slower than uniform_int_distribution
.
Long-story short, use the right tool for the job, don't reinvent the wheel, the STL is well-built, etc. and depending on the use-case one is better than the other.
For yes-no probability (IsPercentChance(float probability)
), bernoulli_distribution
is faster and better.
For pure "give me a random random bool value", uniform_int_distribution
is faster and better.
Vary range of uniform_int_distribution
Distribution objects are lightweight. Simply construct a new distribution when you need a random number. I use this approach in a game engine, and, after benchmarking, it's comparable to using good old rand()
.
Also, I've asked how to vary the range of distribution on GoingNative 2013 live stream, and Stephen T. Lavavej, a member of the standard committee, suggested to simply create new distributions, as it shouldn't be a performance issue.
Here's how I would write your code:
using uint32 = unsigned int;
class Random {
public:
Random() = default;
Random(std::mt19937::result_type seed) : eng(seed) {}
uint32 DrawNumber(uint32 min, uint32 max);
private:
std::mt19937 eng{std::random_device{}()};
};
uint32 Random::DrawNumber(uint32 min, uint32 max)
{
return std::uniform_int_distribution<uint32>{min, max}(eng);
}
Undefined behavior (according to clang -fsanitize=integer) on libstdc++ std::random due to negative index on Mersenne Twister engine
Although as the other answer indicates it is undefined behavior per standard to instantiate std::uniform_int_distribution
with uint8_t
template argument, the UBsan warning here is unrelated to that.
UBSan is flagging the implementation of the Mersenne twister itself, but the implementation doesn't have any undefined behavior or bug.
If you look closely you see that the offending expression is
_M_x[__k + (__m - __n)]
where __k
is a value in the range from (__n - __m)
to (__n - 1)
via the for
loop.
All of the types involved in these operations are std::size_t
which is unsigned. As a consequence these operations all use modular arithmetic and therefore even if __m - __n
is negative and not representable in the unsigned type, the result of
__k + (__m - __n)
will lie between 0
and __m - 1
, so that indexing the array with it is not a problem. No undefined behavior, unspecified behavior or implementation-defined behavior is involved.
The UBSan check which is flagging this is not flagging actual undefined behavior. It is perfectly ok to rely on the wrap-around behavior of unsigned arithmetic like this if one is aware of it. The unsigned overflow check is only meant to be used to flag instances of such wrap-around where it was not intentional. You shouldn't use it on other's code that might rely on it or on your own code if you might be relying on it.
In -fsanitize=address,undefined,nullability,implicit-integer-truncation,implicit-integer-arithmetic-value-change,implicit-conversion,integer
all except address
and undefined
enable UBsan checks which are not flagging actual undefined behavior, but conditions that may be unintentional in many cases. The default -fsanitize=undefined
sanitizer flag doesn't enable the unsigned integer overflow check by default for the reasons given above. See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html for details.
Related Topics
C++ Get String from Clipboard on Linux
Qt Undefined Reference to Vtable
Initializing Map of Maps with Initializer List in VS 2013
Difference Between Dbus and Other Interprocess Communications Method
Compiling Multithread Code with G++ (-Wl,-No-As-Needed Not Working)
Why Doesn't Gcc Support Naked Functions
What Is The Linux Equivalent Of: Multibytetowidechar & Widechartomultibyte
How to Find The Full Path of The C++ Linux Program from Within
Piping Input into a C++ Program to Debug in Visual Studio
How to Subtract Two Gettimeofday Instances
Passing a Non-Copyable Closure Object to Std::Function Parameter
Is Rdtsc Timer Inaccurate in Linux
How to Check That I Didn't Break Anything When Refactoring
Heapcreate, Heapalloc in Linux, Private Allocator for Linux