I am working on a secure LoRa transmission, where I need to generate the same pseudo-random number on the transmitter and the receiver (it would be part of the encryption algorithm) based on an input counter. So this function should give the same output for a given input, just like a hashing algorithm.
As an example here is what I mean, but as you can see the computation gets longer based on the input:
unsigned int f(unsigned int input) {
srand(1234);
for (unsigned int i = 0; i < input; i++) {
rand();
}
return rand();
}
Is there a more efficient way to do this? I am on an ESP32 microcontroller.
edit. Thanks for all the answers. I could have accomplished what I was trying to do with a CRC function, but as per your recommendation I ended up ditching this approach and used a standard encryption algorithm instead.
You should not use rand for this purpose as it is implementation-defined which presents a couple of issues for your use-case:
It may produce different numbers on different targets
It is not guaranteed to be cryptographically secure
What you describe is a cryptographic hash function. There are many libraries available which offer these. Generally there is a trade-off between security and performance, so you will have to select one.
it would be part of the encryption algorithm
If the application must be truly secure, I would recommend using an existing algorithm such as AES rather than trying to write your own, as it appears you are trying to do here. Again, these are available as libraries, some of which are small and suitable for embedded systems such as tiny-AES.
Here a nice question arose today, presenting standard functions for random generation: Get the state (seed) of a distribution of random numbers
Related
Default function is from std::hash. I wonder if there are better hash functions for saving computational time? for integer keys as well as string keys.
I tried City Hash from Google for both integer and string keys, but its performance is a little worse than std::hash.
std::hash functions are already good in performance. I think you should try open source hash functions.
Check this out https://github.com/Cyan4973/xxHash. I quote from its description: "xxHash is an Extremely fast Hash algorithm, running at RAM speed limits. It successfully completes the SMHasher test suite which evaluates collision, dispersion and randomness qualities of hash functions. Code is highly portable, and hashes are identical on all platforms (little / big endian)."
Also this thread from another question on this site: Fast Cross-Platform C/C++ Hashing Library. FNV, Jenkins and MurmurHash are known to be fast.
You need to explain 'better' in what sense? The fastest hash function would be simply use the value, but that is useless. A more specific answer would depend on your memory constraints and what probabilities of collision are you willing to accept.
Also note that the inbuilt hash functions are built differently for different types, and as a result, I expect the hash functions for int and string to already by optimised in the general sense for time complexity and collision probability.
when I want to generate random numbers using std::random, which engine should I prefer? the std::default_random_engine or the std::mt19937? what are the differences?
For lightweight randomnes (e.g. games), you could certainly consider default_random_engine. But if your code depends heavily on quality of randomness (e.g. simulation software), you shouldn't use it, as it gives only minimalistic garantees:
It is the library implemention's selection of a generator that
provides at least acceptable engine behavior for relatively casual,
inexpert, and/or lightweight use.
The mt19937 32 bits mersene twister (or its 64 bit counterpart mt19937_64) is on the other side a well known algorithm that passes very well statistical randomness tests. So it's ideal for scientific applications.
However, you shall consider neither of them, if your randomn numbers are meant for security (e.g. cryptographic) purpose.
The question is currently having one close vote as primary opinion based. I would argue against that and say that std::default_random_engine is objectively a bad choice, since you don't know what you get and switching standard libraries can give you different results in the quality of the randomness you receive.
You should pick whatever random number generator gives you the kind of qualities you are looking for. If you have to pick between the two, go with std::mt19937 as it gives you predictable and defined behaviour.
They address different needs. The first is an implementation-defined alias for a certain generator whilst the latter specifically uses the Mersenne-Twister algorithm with a 32 bit seed.
If you don't have particular requirements, std::default_random_engine should be ok.
I am using the Armadillo c++ library, that allows high-perfomance computation of matrices and vectors. This library has built-in functions to populate its objects with random numbers. I use it in the context of a procedurial random generation of an object. The object creation is random, but no matter how often I recreate the object, it remains the same as long as the seed remains the same.
The issue is that, although I can set the seed to a determined value, and thus recreate the same run on my machine... I lose the coherence of the randomness when going to a different computer. I come from the enchanted land of Matlab where I can specify the function used for the generation of pseudo-random numbers. So, this generation can be cross platform if one chooses the function well. But how do I specify the RNG function for Armadillo?
My research has led me to this source documentation, that "detail" the process of random number generation:
http://arma.sourceforge.net/internal_docs_4300/a01181_source.html
http://arma.sourceforge.net/internal_docs_4300/a00087.html
But i have no clue on what to do here: this code is much more advanced than what I can write. I would appreciate any help!
Thank you guys!
Remarks:
- I do not care how good the random function used is. I just want a fast cross-platform cross-architecture generator. Deterministic randomness is my goal anyway.
- In details, in case it matters, the machines to consider should be intel processors, windows or mac, 32b or 64b.
- I have read the several posts mentionning the use of seeds for randomness but it seems that the problem here is the cross-platform context and the fact that the random generator is buried (to my untrained eyes at least) within Armadillo's code.
In C++98 / C++03 mode, Armadillo will internally use std::rand() for generating random numbers (there's more to it, but that's a good approximation of what's happening).
If you move from one operating system to the next (or across two versions of the same operating system), there is no guarantee that the system provided random number generator will be the same.
If you use Armadillo in C++11 mode, you can use any random number generator you like, with the help of the .imbue() function. Example:
std::mt19937 engine; // Mersenne twister random number engine with default parameters
std::uniform_real_distribution<double> distr(0.0, 1.0);
mat A(123,456);
A.imbue( [&]() { return distr(engine); } ); // fill with random numbers provided by the engine
The Mersenne twister random number engine is provided as standard functionality in C++11. The default parameters should be stable across compiler vendors and versions, and are independent of the operating system.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I've used
#include<stdlib>
#include<time>
using namespace std;
srand((unsigned)time(0));
int n=(rand()>>8)%4;
but what other random functions are there, or what other function could be used as random number generators?
EDIT: I don't really have a particular reason for asking this question, I just wanted to know if C++ had any other random functions.
Boost Random Number Library offers a broad range of generators (quality vs performance) and some typical random distributions. Everything rather nice and straightforward to use.
If you want some other methods/libraries - then google for cryptographic random numbers, also you can use this document as a reference.
Don't invent your own solutions unless you are an expert/researcher in the field/etc, take advantage of already existing solutions which were usually written by Smart People, and thoroughly examined by other Smart People.
The rand() and srand() functions are all the C++ Standard specifies. And if it comes to writing your own, be aware of what John von Neumann said:
"Anyone who considers arithmetical
methods of producing random digits is
of course in a state of sin"
This code is pretty efficient. Although users may begin to notice a pattern after a few iterations.
int FastRandom()
{
return 10;
}
Not strictly C++, but Windows specific:
CryptGenRandom
I'm sure all operating systems have their equivalent cryptographically secure random generator functions.
int unixrand()
{
int x;
int f = open("/dev/random", O_RDONLY);
if (f < 0) return -1; /* Error */
if (sizeof(x) != read(f, &x, sizeof(x))) {
close(f);
return -1;
}
close(f);
if (x < 0) x = ~x;
return x;
}
(Cross-posting from an answer I just wrote to a similar question)
Have a look at ISAAC (Indirection, Shift, Accumulate, Add, and Count). Its uniformly distributed and has an average cycle length of 2^8295.
It's fast too, since it doesnt involve multiplication or modulus.
Bruce Schneier and John Kelsey wrote a random number generator you may be interested in. Rather, it's a seed generator. Even though Yarrow is no longer supported, you may be interested in how it gathers entropy.
OpenSSL has an API that is relatively easy to access and pretty portable. And Mozilla comes with a decent API that wraps whatever the OS offers.
Personally, though, I generally use Boost.Random, which was already suggested.
Random gives you a good random number at uniform distribution and does a pretty good job at that.
Anything else would mean that you want to actually skew the distribution.
For example, using Microsoft's GUIDs generator would give you a random id that is less likely to be repeated and takes into account things like time and computer.
Time is usually the most random operation that is also cheap to perform, but it's still possible to predict.
If you want true randomness, using some kind of external input is your only solution.
Quantum Random Bit Generator is one service that provides such data.
I want to supply a number, and then receive a set of random numbers. However, I want those numbers to be the same regardless of which computer I run it on (assuming I supply the same seed).
Basically my question is: in C++, if I make use of rand(), but supply srand() with a user-defined seed rather than the current time, will I be able to generate the same random number stream on any computer?
There are dozens of PRNGs available as libraries. Pick one. I tend to use Mersenne Twister.
By using an externally supplied library, you bypass the risk of a weird or buggy implementation of your language's library rand(). As long as your platforms all conform to the same mathematical semantics, you'll get consistent results.
MT is a favorite of mine because I'm a physicist, and I use these things for Monte Carlo, where the guarantee of equal-distribution to high dimensions is important. But don't use MT as a cryptographic PRNG!
srand() & rand() are not part of the STL. They're actually part of the C runtime.
Yes, they will produce the same results as long as it's the same implementation of srand()/rand().
Depending on your needs, you might want to consider using Boost.Random. It provides several high-quality random number generators.
Assuming the implementations of rand() are the same, yes.
The easiest way to ensure this is to include a known rand() implementation with your program - either included in your project's source code or in the form of a library you can manage.
No, the ANSI C standard only specifies that rand() must produce a stream of random integers between 0 and RAND_MAX, which must be at least 32767 (source). This stream must be deterministic only in that, for a given implementation on a given machine, it must produce the same integer stream given the same seed.
You want a portable PRNG. Mersenne Twister (many implementations linked at the bottom) is pretty portable, as is Ben Pfaff's homegrown C99-compliant PRNG. Boost.Random should be fine too; as you're writing your code in C++, using Boost doesn't limit your choice of platforms much (although some "lesser" (i.e. non-compliant) compilers may have trouble with its heavy use of template metaprogramming). This is only really a problem for low-volume embedded platforms and perhaps novel research architectures, so if by "any computer" you mean "any x86/PPC/ARM/SPARC/Alpha/etc. platform that GCC targets", any of the above should do just fine.
Write your own pseudorandom number routine. There are a lot of algorithms documented on the internet, and they have a number of applications where rand isn't good enough (e.g. Perlin Noise).
Try these links for starters:
http://en.wikipedia.org/wiki/Linear_congruential_generator
http://en.wikipedia.org/wiki/Pseudorandom_number_generator
I believe if you supply with srand with the same seed, you will get the same results. That's pretty much the definition of a seed in terms of pseudo random number generators.
Yes. For a given seed (starting value), the sequence of numbers that rand() returns will always be the same.