Migrating C # to Python - Random Class
I need to port some C # code to Python. The source code uses the class Random
. The ported code must be precise (more precisely, successive calls Next()
must produce the same results in both codes). Some questions:
- Is there an equivalent to calling C #
Random
in Python? - Anyway, assuming I can change both sources, is there a pseudo-random library that works with both C # and Python?
source to share
I don't know of any library available for both Python and C # that generates the same random numbers for both. However, you can take advantage of IronPython. The default implementation Random
is different from IronPython and CPython, but the class WichmannHill
doesn't work.
You can use C # to instantiate a class WichmannHill
in IronPython and get the same values as CPython for the same semester. Alternatively, you can implement the Wichmann-Hill algorithm in C # relatively easily by translating the Python code into random.py
.
Another option is to take the CPython implementation from Random
the Mersenne Twister algorithm and translate it to C # to get identical results.
source to share
I know this is an old question, but I still needed to solve this. I ended up implementing the C # Random class in python. It works as long as you don't need random numbers greater than 2147483647 and I don't need this functionality, so I left it unfinished.
https://gist.github.com/BadStreff/541cf2e6953b3c666f83127a1d4f6a47
from ctypes import *
# implemented from:
# http://referencesource.microsoft.com/#mscorlib/system/random.cs,dec894a7e816e665
class Random(object):
def __init__(self, seed):
self.seed = c_int(seed).value
self.MBIG = 2147483647
self.MMIN = -2147483648
self.MZ = 0
self.MSEED = 161803398
self.SeedArray = [0] * 56
if seed == self.MMIN:
subtraction = self.MBIG
else:
subtraction = abs(seed)
mj = c_int(self.MSEED - subtraction).value
self.SeedArray[55] = mj
mk = 1
for i in range(1, 55):
ii = (21 * i) % 55
self.SeedArray[ii] = mk
mk = mj - mk
if mk < 0:
mk += self.MBIG
mj = self.SeedArray[ii]
for k in range(1, 5):
for i in range(1, 56):
self.SeedArray[i] -= self.SeedArray[1 + (i + 30) % 55]
if self.SeedArray[i] < 0:
self.SeedArray[i] = c_int(self.SeedArray[i] + self.MBIG).value
self.inext = 0
self.inextp = 21
self.seed = 1
def InternalSample(self):
locINext = self.inext + 1
locINextp = self.inextp + 1
if locINext >= 56:
locINext = 1
if locINextp >= 56:
locINextp = 1
retVal = c_int(self.SeedArray[locINext] - self.SeedArray[locINextp]).value
if retVal == self.MBIG:
retVal -= 1
if retVal < 0:
retVal = c_int(retVal + self.MBIG).value
self.SeedArray[locINext] = retVal
self.inext = locINext
self.inextp = locINextp
return retVal
def Next(self, minValue=None, maxValue=None):
if minValue == None:
return self.InternalSample()
valRange = maxValue - minValue
if valRange <= self.MBIG:
return int(c_float(self.Sample() * valRange).value) + minValue
else:
return self.GetSampleForLargeRange() * valRange + minValue
def GetSampleRangeForLargeRange(self):
pass
def Sample(self):
s = self.InternalSample()
ret = c_double(s * c_double(1.0/self.MBIG).value).value
# print(f'sample: {s}\nret: {ret}')
return ret
source to share