如何让这个PRNG生成范围内的数字?

How to get this PRNG to generate numbers within the range?

我发现 this 是我在下面制作的,对于 JavaScript 中的 8 位和 16 位数字:

const fetch = (x, o) => {
  if (x >= o) {
    return x
  } else {
    const v = (x * x) % o
    return (x <= o / 2) ? v : o - v
  }
}

const fetch16 = (x) => fetch(x, 65519)
const fetch8 = (x) => fetch(x, 251)

// the last number can be anything.
const build16 = (x, o) => fetch16((fetch16(x) + o) ^ 42703)
const build8 = (x, o) => fetch8((fetch8(x) + o) ^ 101)

let i = 0
let invalid = []
while (i < 255) {
  let j = 0
  while (j < 255) {
    let x = build8(i, j)
    if (x > 255) {
      invalid.push([ i, j, x ])
    }
    j++
  }
  i++
}

console.log(JSON.stringify(invalid))

但是,虽然 fetch8fetch16 功能正常 在重复之前循环遍历整个数字集build8build16 函数没有,它们超出了所需的范围,请参阅上面代码的输出。例如,当i = 11j = 184时,x = 340,即> 255.

然而,这些 build8build16 函数的输出非常棒。它看起来完全随机,并且在遍历整个集合之前不会重复任何值。

我如何修改这些 build8build16 函数,使它们只包含集合中的数字(0-255 或 0-65535),但像它们在这里一样完全随机出现, 但在遍历所有值之前从不重复一个值?

我不完全确定 post 的作者是如何找到 fetch8((fetch8(x) + o) ^ 101) 的,例如,执行 XOR 并传递这样的值。但最终结果显得非常随机。我只想让它输出为:

您超出范围值的原因是尽管 fetchXX 会产生范围内的值,但 + o 破坏了这个 属性。 XOR 运算 可能 有时会将其带回范围内,但并非总是如此。

所以你应该对+ o之后的值取模。异或运算永远不会超出范围,所以可以保持原样。

其次,要测试是否没有生成重复项,您需要修复传递给 buildXX 函数的两个参数之一,而只改变另一个。冻结第二个参数对我来说似乎更合乎逻辑。

这就是它的样子:

const fetch = (x, o) => {
  if (x >= o) {
    return x
  } else {
    const v = (x * x) % o
    return (x <= o / 2) ? v : o - v
  }
}

const fetch16 = (x) => fetch(x, 65519)
const fetch8 = (x) => fetch(x, 251)

// the last number can be anything.
const build16 = (x, o) => fetch16((fetch16(x) + o) % 65536 ^ 42703)
const build8 = (x, o) => fetch8((fetch8(x) + o) % 256 ^ 101)

const j = 115; // If you don't want duplicates, either i or j should stay fixed
let i = 0
let invalid = [];
let valid = new Set;
while (i <= 255) { // <-- small fix here!
    let x = build8(i, j); // To test, you can swap i and j here, and run again.
    if (x > 255) {
        invalid.push([ i, j, x ]);
    } else {
        valid.add(x);
    }
    i++;
}

console.log("invalid:", JSON.stringify(invalid));
console.log("count of valid:", valid.size);