javascript - 将 C++ 程序翻译成 JavaScript/asm.js 不会产生相同的数字序列
问题描述
我从 Agner Fog 的库中获取了所有随机数生成器的母亲,并尝试制作它的 JavaScript 版本。我希望位模式是相同的,但情况似乎并非如此,我想知道为什么或者我是否犯了错误?
我使用的 C++ 代码可以在这里找到。它来自 Agner Fog 的网站。
这是我的 TypeScript 版本的代码
const u = (function () {
const b = new ArrayBuffer(8)
return {
u32: new Uint32Array(b),
u64: new BigUint64Array(b),
}
})()
export class Random {
state = new Uint32Array(5)
constructor(seed?: number) {
this.seed(seed ?? +new Date())
}
b() {
const { state: x } = this
u.u64[0] =
2111111111n * BigInt(x[3]) +
1492n * BigInt(x[2]) +
1776n * BigInt(x[1]) +
5115n * BigInt(x[0]) +
BigInt(x[4])
console.debug(u.u64[0])
x[3] = x[2]
x[2] = x[1]
x[1] = x[0]
x[4] = u.u32[1]
x[0] = u.u32[0]
return x[0]
}
next() {
return (1 / 4_294_967_296) * this.b()
}
seed(seed: number) {
const { state: x } = this
let s = seed >>> 0
// make random numbers and put them into the buffer
for (let i = 0; i < 5; i++) {
s = s * 29943829 - 1
x[i] = s
}
console.debug(x)
// randomize some more
for (let i = 0; i < 19; i++) {
this.b()
}
}
}
我设法把它归结为状态初始化,但我不明白为什么 C++ 程序的输出是4294967295
, 4265023466
, 1627457073
, 3925469700
,2226377299
但是 TypeScript 程序给了我4294967295
, 4265023466
, 1627457073
, 3925868544
, 0
. 只有前 3 个数字的计算结果完全相同。非常感谢任何试图理解这一点的帮助。
解决方案
啊,我想通了。我必须使用Math.imul
才能获得正确的结果。没有它就不能做类似 C 的整数乘法。
所以这:
for (let i = 0; i < 5; i++) {
s = s * 29943829 - 1
x[i] = s
}
...更改为:
for (let i = 0; i < 5; i++) {
s = Math.imul(s, 29943829) - 1
x[i] = s
}
我尝试过类似的东西,(s * 29943829) >>> 0
但这还不足以强制 C 风格的整数乘法。
推荐阅读
- javascript - 自执行功能是否被认为是 nodejs 模块中的一个好习惯?
- php - 如何访问此 JSON 信息 (PHP)?
- python - Python没有像我预期的那样增加循环
- java - 为什么执行一组测试会给出不同的结果,如果单独执行?
- raspberry-pi3 - Raspberry pi 文本输入语音输出上的 Google Assistant
- python - 应用程序和服务列表?
- arrays - 使用结构类型时出现意外错误
- django - 如何从 django 框架中的 ModelForm 字段中获取特定值?
- delphi - 在 delphi Berlin 中添加 Soap Header
- laravel - 返回 Laravel 中模型记录属性为空的集合