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?
+3


source to share


2 answers


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.

+1


source


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

      

+1


source







All Articles