我需要将一些 C# 代码迁移到 Python。原始代码使用了Random
该类。迁移的代码必须是循环准确的(即连续调用Next()
必须在两个代码中产生相同的结果)。一些问题:
Random
Python 中是否有与 C# 等效的调用?- 头韵,假设我可以修改这两个源,是否有一个伪随机库同时适用于 C# 和 Python?
我知道这是一个老问题,但我最终需要一个解决方案。我最终在 python 中实现了 C# 的 Random 类。只要您不需要大于 2147483647 的随机数,它就可以工作,我最终不需要该功能,所以我没有实现它。
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
我不知道有任何库可用于 Python 和 C# 并且为两者生成相同的随机数。但是,您也许可以利用 IronPython。IronPython 和 CPython的默认Random
实现不同,但WichmannHill
类没有。
您可以使用 C#WichmannHill
在 IronPython 中实例化类,并为相同的种子获取与 CPython 相同的值。或者,您可以通过将 Python 代码翻译成random.py
.
另一种选择是采用 Mersenne Twister 算法的CPython实现Random
并将其转换为 C# 以获得相同的结果。