I was wondering if there was any way to generate a random number, from 1 to 9, without using external libraries, even if they are included with Python.This is a dumb reason, but my editor doesn't allow any libraries, so I need a way to get randomness without libraries.
You need something to start with. Random numbers can be spawned from the last the few digits in the milliseconds value from the system's timestamp. Then you can manipulate them a little and tadah : a different random number every time.
You can implement a random number generator in plain Python, but they all need a seed. The reason Xorshift always returned the same sequence to #yuwe is that it's always getting the same seed. Same seed => same sequence of pseudo-random numbers.
Getting a suitable seed is not possible without resorting to external entropy sources, be it the current time in microseconds, the current process ID, the number of bytes sent over the network since the last reboot, mouse movements, what have you.
Related
One friend that I don't have any communication with anymore once told me the following:
Using that library(python's random) you can select a seed If you give it at seed it
means the randomly generated number will always be the same No matter
what computer you run it on
So I tried to test this, because this is what I need so it's the same on all computers and everytime someone calls this(this is important, as I am working on a blockchain NFT and trust is important here)
So I found this: https://machinelearningmastery.com/how-to-generate-random-numbers-in-python/
on that link, there's example:
from random import seed
from random import random
# seed random number generator
seed(1)
# generate some random numbers
print(random(), random(), random())
# reset the seed
seed(1)
# generate some random numbers
print(random(), random(), random())
running above in playground of python, I get
(0.417022004703, 0.720324493442, 0.000114374817345) (0.417022004703,
0.720324493442, 0.000114374817345)
But as you can see, on that website, the creator of that post got the following:
0.13436424411240122 0.8474337369372327 0.763774618976614
0.13436424411240122 0.8474337369372327 0.763774618976614
Why aren't they same on all computers then ? I am using the same seed. and how can I ensure that they will be the same ?
The ANSWER is that, even though you have tagged Python-3.x, you are actually using Python 2, and the random number algorithm changed between 2 and 3.
I can tell that because your print statement printed the values as a tuple, with parentheses. That wouldn't happen with Python 3's print function.
It's odd to rely on a particular implementation of a random number algorithm for financial purposes. If you really need reproducibility, then you should embed your own algorithm. There are several RNGs that are not difficult to code. But if the algorithm needs to be predictable, why not just use incrementing numbers? If you don't need randomness, then don't use randomness.
I get the post author's values both in Python 2.3.0 (over 18 years old) and in Python 3.10 (the newest, just a month old).
I get your values if I use numpy.random instead of Python's random.
So I suspect you're not telling the truth about your code or that that "playground of python" you're using is weird.
From the docs:
random.seed(a=None, version=2) Initialize the random number generator.
If a is omitted or None, the current system time is used. If
randomness sources are provided by the operating system, they are used
instead of the system time (see the os.urandom() function for details
on availability).
But...if it's truly random...(and I thought I read it uses Mersenne, so it's VERY random)...what's the point in seeding it? Either way the outcome is unpredictable...right?
The default is probably best if you want different random numbers with each run. If for some reason you need repeatable random numbers, in testing for instance, use a seed.
The module actually seeds the generator (with OS-provided random data from urandom if possible, otherwise with the current date and time) when you import the module, so there's no need to manually call seed().
(This is mentioned in the Python 2.7 documentation but, for some reason, not the 3.x documentation. However, I confirmed in the 3.x source that it's still done.)
If the automatic seeding weren't done, you'd get the same sequence of numbers every time you started your program, same as if you manually use the same seed every time.
But...if it's truly random
No, it's pseudo random. If it uses Mersenne Twister, that too is a PRNG.
It's basically an algorithm that generates the exact same sequence of pseudo random numbers out of a given seed. Generating truly random numbers requires special hardware support, it's not something you can do by a pure algorithm.
You might not need to seed it since it seeds itself on first use, unless you have some other or better means of providing a seed than what is time based.
If you use the random numbers for things that are not security related, a time based seed is normally fine. If you use if for security/cryptography, note what the docs say: "and is completely unsuitable for cryptographic purposes"
If you want to reproduce your results, you seed the generator with a known value so you get the same sequence every time.
A Mersenne twister, the random number generator, used by Python is seeded by the operating system served random numbers by default on those platforms where it is possible (Unixen, Windows); however on other platforms the seed defaults to the system time which means very repeatable values if the system time has a bad precision. On such systems seeding with known better random values is thus beneficial. Note that on Python 3 specifically, if version 2 is used, you can pass in any str, bytes, or bytearray to seed the generator; thus taking use of the Mersenne twister's large state better.
Another reason to use a seed value is indeed to guarantee that you get the same sequence of random numbers again and again - by reusing the known seed. Quoting the docs:
Sometimes it is useful to be able to reproduce the sequences given by
a pseudo random number generator. By re-using a seed value, the same
sequence should be reproducible from run to run as long as multiple
threads are not running.
Most of the random module’s algorithms and seeding functions are
subject to change across Python versions, but two aspects are
guaranteed not to change:
If a new seeding method is added, then a backward compatible seeder will be offered.
The generator’s random() method will continue to produce the same sequence when the compatible seeder is given the same seed.
For this however, you mostly want to use the random.Random instances instead of using module global methods (the multiple threads issue, etc).
Finally also note that the random numbers produced by Mersenne twister are unsuitable for cryptographical use; whereas they appear very random, it is possible to fully recover the internal state of the random generator by observing only some hundreds of values from the generator. For cryptographical algorithms, you want to use the SystemRandom class.
In most cases I would say there is no need to care about. But if someone is really willing to do something wired and (s)he could roughly figure out your system time when your code was running, they might be able to brute force replay your random numbers and see which series fits. But I would say this is quite unlikely in most cases.
From the docs:
random.seed(a=None, version=2) Initialize the random number generator.
If a is omitted or None, the current system time is used. If
randomness sources are provided by the operating system, they are used
instead of the system time (see the os.urandom() function for details
on availability).
But...if it's truly random...(and I thought I read it uses Mersenne, so it's VERY random)...what's the point in seeding it? Either way the outcome is unpredictable...right?
The default is probably best if you want different random numbers with each run. If for some reason you need repeatable random numbers, in testing for instance, use a seed.
The module actually seeds the generator (with OS-provided random data from urandom if possible, otherwise with the current date and time) when you import the module, so there's no need to manually call seed().
(This is mentioned in the Python 2.7 documentation but, for some reason, not the 3.x documentation. However, I confirmed in the 3.x source that it's still done.)
If the automatic seeding weren't done, you'd get the same sequence of numbers every time you started your program, same as if you manually use the same seed every time.
But...if it's truly random
No, it's pseudo random. If it uses Mersenne Twister, that too is a PRNG.
It's basically an algorithm that generates the exact same sequence of pseudo random numbers out of a given seed. Generating truly random numbers requires special hardware support, it's not something you can do by a pure algorithm.
You might not need to seed it since it seeds itself on first use, unless you have some other or better means of providing a seed than what is time based.
If you use the random numbers for things that are not security related, a time based seed is normally fine. If you use if for security/cryptography, note what the docs say: "and is completely unsuitable for cryptographic purposes"
If you want to reproduce your results, you seed the generator with a known value so you get the same sequence every time.
A Mersenne twister, the random number generator, used by Python is seeded by the operating system served random numbers by default on those platforms where it is possible (Unixen, Windows); however on other platforms the seed defaults to the system time which means very repeatable values if the system time has a bad precision. On such systems seeding with known better random values is thus beneficial. Note that on Python 3 specifically, if version 2 is used, you can pass in any str, bytes, or bytearray to seed the generator; thus taking use of the Mersenne twister's large state better.
Another reason to use a seed value is indeed to guarantee that you get the same sequence of random numbers again and again - by reusing the known seed. Quoting the docs:
Sometimes it is useful to be able to reproduce the sequences given by
a pseudo random number generator. By re-using a seed value, the same
sequence should be reproducible from run to run as long as multiple
threads are not running.
Most of the random module’s algorithms and seeding functions are
subject to change across Python versions, but two aspects are
guaranteed not to change:
If a new seeding method is added, then a backward compatible seeder will be offered.
The generator’s random() method will continue to produce the same sequence when the compatible seeder is given the same seed.
For this however, you mostly want to use the random.Random instances instead of using module global methods (the multiple threads issue, etc).
Finally also note that the random numbers produced by Mersenne twister are unsuitable for cryptographical use; whereas they appear very random, it is possible to fully recover the internal state of the random generator by observing only some hundreds of values from the generator. For cryptographical algorithms, you want to use the SystemRandom class.
In most cases I would say there is no need to care about. But if someone is really willing to do something wired and (s)he could roughly figure out your system time when your code was running, they might be able to brute force replay your random numbers and see which series fits. But I would say this is quite unlikely in most cases.
In a view in django I use random.random(). How often do I have to call random.seed()?
One time for every request?
One time for every season?
One time while the webserver is running?
Don't set the seed.
The only time you want to set the seed is if you want to make sure that the same events keep happening. For example, if you don't want to let players cheat in your game you can save the seed, and then set it when they load their game. Then no matter how many times they save + reload, it still gives the same outcomes.
Call random.seed() rarely if at all.
To be random, you must allow the random number generator to run without touching the seed. The sequence of numbers is what's random. If you change the seed, you start a new sequence. The seed values may not be very random, leading to problems.
Depending on how many numbers you need, you can consider resetting the seed from /dev/random periodically.
You should try to reset the seed just before you've used up the previous seed. You don't get the full 32 bits of randomness, so you might want to reset the seed after generating 2**28 numbers.
It really depends on what you need the random number for. Use some experimentation to find out if it makes any difference. You should also consider that there is actually a pattern to pseudo-random numbers. Does it make a difference to you if someone can possible guess the next random number? If not, seed it once at the start of a session or when the server first starts up.
Seeding once at the start of the session would probably make the most sense, IMO. This way the user will get a set of pseudo-random numbers throughout their session. If you seed every time a page is served, they aren't guaranteed this.
Simple enough question:
I'm using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this default to the current time, but this is not ideal. It seems like a string literal constant (similar to a password) would also not be ideal/strong
Suggestions?
Thanks,
-aj
UPDATE:
The reason I am generating random integers is for generation of test data. The numbers do not need to be reproducable.
According to the documentation for random.seed:
If x is omitted or None, current system time is used; current system time is also used to initialize the generator when the module is first imported. If randomness sources are provided by the operating system, they are used instead of the system time (see the os.urandom() function for details on availability).
If you don't pass something to seed, it will try to use operating-system provided randomness sources instead of the time, which is always a better bet. This saves you a bit of work, and is about as good as it's going to get. Regarding availability, the docs for os.urandom tell us:
On a UNIX-like system this will query /dev/urandom, and on Windows it will use CryptGenRandom.
Cross-platform random seeds are the big win here; you can safely omit a seed and trust that it will be random enough on almost every platform you'll use Python on. Even if Python falls back to the time, there's probably only a millisecond window (or less) to guess the seed. I don't think you'll run into any trouble using the current time anyway -- even then, it's only a fallback.
For most cases using current time is good enough. Occasionally you need to use a fixed number to generate pseudo random numbers for comparison purposes.
Setting the seed is for repeatability, not security. If anything, you make the system less secure by having a fixed seed than one that is constantly changing.
Perhaps it is not a problem in your case, but ont problem with using the system time as the seed is that someone who knows roughly when your system was started may be able to guess your seed (by trial) after seeing a few numbers from the sequence.
eg, don't use system time as the seed for your online poker game
If you are using random for generating test data I would like to suggest that reproducibility can be important.
Just think to an use case: for data set X you get some weird behaviour (eg crash). Turns out that data set X shows some feature that was not so apparent from the other data sets Y and Z and uncovers a bug which had escapend your test suites. Now knowing the seed is useful so that you can precisely reproduce the bug and you can fix it.