将定制的随机生成器从 JS 移植到 Python 3
Porting bespoke random generator from JS to Python 3
伙计们。
我发现 here 一个非常基本的随机生成器,具有播种功能。
还将代码作为片段附上。
var m_w = 123456789;
var m_z = 987654321;
var mask = 0xffffffff;
// Takes any integer
function seed(i) {
m_w = (123456789 + i) & mask;
m_z = (987654321 - i) & mask;
}
// Returns number between 0 (inclusive) and 1.0 (exclusive),
// just like Math.random().
function random()
{
m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}
seed(1);
console.log(random())
console.log(random())
console.log(random())
console.log(random())
console.log(random())
我正在尝试将其移植到 Python 3 并意识到按位运算存在差异,因为 JS 和 Python 对长整数的行为不同。
目前的Python代码是:
#!/usr/bin/python
import ctypes
m_w = 123456789
m_z = 987654321
mask = 0xFFFFFF
#JS returns 123456790, 987654320
def bespokeSeed(seed_):
global m_w, m_z, mask
m_w = m_w + seed_
m_z = m_z - seed_
def bespokeRandom():
global m_w, m_z, mask
#JS returns 990784270, 945037883
m_z = (36969 * (m_z & 65535 & (2**53-1)) + (m_z >> 16) & (2**53-1))
m_w = (18000 * (m_w & 65535 & (2**53-1)) + (m_w >> 16) & (2**53-1))
#JS returns 722346555
result = ((ctypes.c_int(m_z << 16 ^ 0).value + ctypes.c_int(m_w & 65535 ^ 0).value) >> 0) / 4294967296
return result
bespokeSeed(1)
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
JS代码(调用5次random())returns
0.16818441334180534
0.7648323038592935
0.1521853597369045
0.22241602488793433
0.4391189150046557
而 Python 得到
0.16818441334180534
-0.23516769614070654
0.1521853597369045
0.22241602488793433
0.4391189150046557
如您所见,它部分有效,但在返回负数时存在一些问题。
关于如何修复它有什么想法吗?
我完全不明白为什么你有 ctypes。问题是 Javascript 整数限制为 32 位,而 Python 具有无限精度。这就是你想要的:
import ctypes
m_w = 123456789
m_z = 987654321
mask = 0xFFFFFFFF
def bespokeSeed(seed_):
global m_w, m_z
m_w = m_w + seed_
m_z = m_z - seed_
def bespokeRandom():
global m_w, m_z
#JS returns 990784270, 945037883
m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask
m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask
result = ((m_z << 16 & mask) + (m_w & 65535)) / 4294967296
return result
bespokeSeed(1)
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
伙计们。
我发现 here 一个非常基本的随机生成器,具有播种功能。 还将代码作为片段附上。
var m_w = 123456789;
var m_z = 987654321;
var mask = 0xffffffff;
// Takes any integer
function seed(i) {
m_w = (123456789 + i) & mask;
m_z = (987654321 - i) & mask;
}
// Returns number between 0 (inclusive) and 1.0 (exclusive),
// just like Math.random().
function random()
{
m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}
seed(1);
console.log(random())
console.log(random())
console.log(random())
console.log(random())
console.log(random())
我正在尝试将其移植到 Python 3 并意识到按位运算存在差异,因为 JS 和 Python 对长整数的行为不同。
目前的Python代码是:
#!/usr/bin/python
import ctypes
m_w = 123456789
m_z = 987654321
mask = 0xFFFFFF
#JS returns 123456790, 987654320
def bespokeSeed(seed_):
global m_w, m_z, mask
m_w = m_w + seed_
m_z = m_z - seed_
def bespokeRandom():
global m_w, m_z, mask
#JS returns 990784270, 945037883
m_z = (36969 * (m_z & 65535 & (2**53-1)) + (m_z >> 16) & (2**53-1))
m_w = (18000 * (m_w & 65535 & (2**53-1)) + (m_w >> 16) & (2**53-1))
#JS returns 722346555
result = ((ctypes.c_int(m_z << 16 ^ 0).value + ctypes.c_int(m_w & 65535 ^ 0).value) >> 0) / 4294967296
return result
bespokeSeed(1)
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
JS代码(调用5次random())returns
0.16818441334180534
0.7648323038592935
0.1521853597369045
0.22241602488793433
0.4391189150046557
而 Python 得到
0.16818441334180534
-0.23516769614070654
0.1521853597369045
0.22241602488793433
0.4391189150046557
如您所见,它部分有效,但在返回负数时存在一些问题。 关于如何修复它有什么想法吗?
我完全不明白为什么你有 ctypes。问题是 Javascript 整数限制为 32 位,而 Python 具有无限精度。这就是你想要的:
import ctypes
m_w = 123456789
m_z = 987654321
mask = 0xFFFFFFFF
def bespokeSeed(seed_):
global m_w, m_z
m_w = m_w + seed_
m_z = m_z - seed_
def bespokeRandom():
global m_w, m_z
#JS returns 990784270, 945037883
m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask
m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask
result = ((m_z << 16 & mask) + (m_w & 65535)) / 4294967296
return result
bespokeSeed(1)
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())
print(bespokeRandom())