0

I am looking for a Python function that will mimic the behavior of rand() (and srand()) in c with the following requirements:

  1. I can provide the same epoch time into the Python equivalent of srand() to seed the function
  2. The equivalent of rand()%256 should result in the same char value as in c if both were provided the same seed.

So far, I have considered both the random library and numpy's random library. Instead of providing a random number from 0 to 32767 as C does though both yield a floating point number from 0 to 1 on their random functions. When attempting random.randint(0,32767), I yielded different results than when in my C function.

TL;DR Is there an existing function/libary in Python that follows the same random sequence as C?

user3439632
  • 55
  • 1
  • 6
  • 5
    I doubt there is only one implementation of rand across all C environments. – stark Feb 21 '20 at 04:00
  • 4
    The output of C's `rand` is completely unspecified. There is no guaranteed sequence. If you want a guaranteed sequence, you shouldn't be using `rand`. – user2357112 Feb 21 '20 at 04:02
  • 1
    (Also, the statistical quality of `rand` output is typically terrible.) – user2357112 Feb 21 '20 at 04:04
  • To clarify, this is in the context of a cryptography problem where I know a range of possible times that a file was encrypted and know that the srand() seed was set with the epoch time during the period with a c algorithm. I am looking for a way to solve this problem in python with the knowledge that the cipher key was generated with c's rand(). rand() will produce the same sequence given a particular srand() seed – user3439632 Feb 21 '20 at 04:09
  • @user3439632: A given implementation of C will produce a predictable sequence of random numbers. It's likely that the same sequence will be produced by another machine with the same platform, although different library versions might produce different sequences. But you will not necessarily get the same sequence on two different platforms. Try it, for example, on a machine running Linux and another one running OS X. Or Windows. "C" does not specify a pseudo random number generation algorithm for `rand()`. – rici Feb 21 '20 at 04:21
  • 2
    ... so, this is a job for FFI, to let you call the actual C implementations from Python, with the understanding that you need to call it in a system that's similar enough to the system you're trying to emulate (same libc, same architecture, maybe same compile time flags, etc). See, for example, https://docs.python.org/3/library/ctypes.html – Charles Duffy Feb 21 '20 at 04:28

3 Answers3

7

You can accomplish this with CDLL from https://docs.python.org/3/library/ctypes.html

from ctypes import CDLL

libc = CDLL("libc.so.6")
libc.srand(42)
print(libc.rand() % 32768)
novafacing
  • 86
  • 1
  • 2
4

You can't make a Python version of rand and srand functions "follo[w] the same random sequence" of C's rand and srand because the C standard doesn't specify exactly what that sequence is, even if the seed is given. Notably:

  • rand uses an unspecified pseudorandom number algorithm, and that algorithm can differ between C implementations, including versions of the same standard library.
  • rand returns values no greater than RAND_MAX, and RAND_MAX can differ between C implementations.

In general, the best way to "sync" PRNGs between two programs in different languages is to implement the same PRNG in both languages. This may be viable assuming you're not using pseudorandom numbers for information security purposes. See also this question: How to sync a PRNG between C#/Unity and Python?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
-1

You can use random.seed(). The following example should print the same sequence every time it runs:

import random
random.seed(42)
for _ in range(10):
    print(random.randint(0, 32768))

Update: Just saw the last comment by the OP. No, this code won't give you the same sequence as the C code, because of reasons given in other comments. Two different C implementations won't agree either.

Selcuk
  • 57,004
  • 12
  • 102
  • 110