简体   繁体   中英

How to make a truly improbable condition with limitations of Python's random?

So I am trying to find a way to get a massively improbable condition based on random generations. To better explain, here's an example:

from random import *
import ctypes

random1 = [randint(0, 2 ** 32 - 1) for j in range(10000000)]

while True:
    random2 = [randint(0, 2 ** 32 - 1) for i in range(10000000)]
    if set(random2) == set(random1):
        MessageBox = ctypes.windll.user32.MessageBoxW
        MessageBox(None, 'Match', 'Output', 0)
        break

Because of the limitations and functionality of mersene twister, and the uniformity of its distribution of numbers, it's quite likely we will generate 10 milion numbers in both lists, where when order doesn't matter and duplicates are removed, they will match quite often.

This is not that rare, but the following code is slightly better:

from random import *
import ctypes

while True:
    if random() == 0.0:
        MessageBox = ctypes.windll.user32.MessageBoxW
        MessageBox(None, 'Match', 'Output', 0)
        break

This is a lot less likely to happen, but with massive single core performance, quite common today, it's still easily likely to get a match in 1~ day. The probability being 1/2^56, and with the limitations of mersenne twister in mind, it's not that unlikely to happen.

Is there a good way to write a condition utilizing randomness in python that will truly be extremely unlikely to happen?.. That would say, take a year to crack, or more.

Alternatively I thought to turn to hash matching... creating a random SHA256 hash, then generating random big data, and hashing it through sha256 to try and match the hash. But I don't know a way to observe probability in that case.

You may be interested in the geometric distribution , which counts the number of failures before the first success (some works say it counts that number plus the first success instead). As an example, the probability of getting no failures in a row is 1/2, one failure in a row is 1/4, two in a row is 1/8, three in a row is 1/16, and so on. If we take a zero-bit to mean failure and a one-bit to mean success, that means that with more zero-bits, it becomes less probable for that many zero-bits to be generated at random. As an example of an "improbable event", you can treat 30 or more zero-bits in a row as improbable.

Mersenne Twister and pseudorandom number generators (PRNGs) in general have cycles. The size of this cycle affects how many zero-bits the PRNG can generate in a row. For example, Mersenne Twister has a cycle of 2^19937 - 1 numbers, so that in theory, it can cycle through all states except for the all-zeros state. Thus, it can generate no more than 19937 * 2 zero-bits in a row. (This is if we treat Mersenne Twister as outputting individual bits, rather than 32 bits, at a time.)

This is in contrast to nondeterministic random number generators (RNGs), which don't have cycles but still generate random-behaving numbers. If the numbers it generates are independent, uniform, and random bits, then there is no telling how many zero-bits the RNG can randomly generate at most. One example of an RNG that uses nondeterminism is found in Python's secrets module, specifically secrets.randbelow() . (In practice, this module is likely to use a PRNG, but may gather "entropy" from nondeterministic sources from time to time, so that in practice the module's RNG is nondeterministic.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM