Javascript-此噪声函数会起作用吗?

时间:2019-04-16 10:57:36

标签: javascript random noise

我已经在C#和C ++地形生成器中使用了一段时间的以下确定性噪声函数:

float GridNoise(int x, int z, int seed)
{
    int n = (1619*x + 31337*z + 1013*seed) & 0x7fffffff;
    n = (n >> 13) ^ n;

    return 1 - ((n*(n*n*60493 + 19990303) + 1376312589) & 0x7fffffff)/(float)1073741824;
}

对于我输入的任何整数x / z坐标,它返回1到-1之间的“随机”浮点数(另外还有一个种子,因此我可以生成不同的地形)。我尝试在Javascript中实现相同的功能,但结果与预期的不同。对于较小的值,似乎还可以,但是当我使用较大的值(大约10000)时,结果的随机性就会越来越少,最终返回的结果都是1。

您可以看到它在C#here中正常工作,并且对于相同的输入here,JS结果不正确。

我怀疑这与JS变量不是严格的整数有关,但是有人可以阐明更多吗?如果不起作用,有人可以在JS中使用类似的简单确定性函数吗?

4 个答案:

答案 0 :(得分:1)

潜在的问题是,在javascript中,没有整数-因此所有数学函数都使用数字(52位精度浮点数)完成

在c#中,如果您使用多头,那么所有溢出都将被丢弃

在javascript中,您需要自己处理

浏览器将使用一种数字格式,这将有所帮助,但目前还不行-BigInt ...它位于chrome / opera中,并且位于firefox(台式机,而非android)中的标志后面

(Edge(无论如何还是死了)或Safari(新IE)上都没有字-当然,IE永远不会得到它们)

使用BigInt最好的方法是

function gridNoise(x, z, seed) {
    var n = (1619 * x + 31337 * z + 1013 * seed) & 0x7fffffff;
    n = BigInt((n >> 13) ^ n);
    n = n * (n * n * 60493n + 19990303n) + 1376312589n;
    n = parseInt(n.toString(2).slice(-31), 2);
    return 1 - n / 1073741824;
}

function test() {
    for (var i = 10000; i < 11000; i++) {
        console.log(gridNoise(0, 0, i));
    }
}
test();

请注意,60493nBigInt表示法

在过渡期间,您可以使用“大整数”库-https://github.com/peterolson/BigInteger.js

  

以下内容将不起作用,也永远不会...因为32位x 32位== 64位...所以您已经丢失了位

     

我误读了代码,尽管n只有19位(因为>> 13)

如果将n * n * 60493的结果限制为32bit,(实际上,我将其设置为31bit ...因此,无论如何,它似乎都可以正常工作

function gridNoise(x, z, seed) {
  var n = (1619 * x + 31337 * z + 1013 * seed) & 0x7fffffff;
  n = (n >> 13) ^ n;

  return 1 - ((n * (n * n * 60493 & 0x7fffffff + 19990303) + 1376312589) & 0x7fffffff) / 1073741824;
}

这也有效

return 1 - ((n*(n*n*60493 | 0 + 19990303)  + 1376312589) & 0x7fffffff)/1073741824;

这会将临时结果限制为32位,该结果可能是“准确的”,也可能不是“准确的”。

如果您想精确复制c#生成的内容,则可能需要使用它

答案 1 :(得分:0)

恐怕您的代码超出了整数的最大大小限制。一旦发生这种情况,它将返回1,因为计算((n*(n*n*60493 + 19990303) + 1376312589) & 0x7fffffff)/1073741824将始终为0-因此1-0 = 1

答案 2 :(得分:0)

要了解这里发生的情况,必须检查JavaScript number类型。它基本上是一个53位整数,使用另一个11位整数向左/向右移位,得到一个64位数字。因此,如果您的计算结果为54位整数,则只需要高位 53位,然后将它们左移1位。现在,如果对数字进行按位数学运算,则需要较低的32位。因此,如果整数大于84位,则对其进行按位移位将始终为0。因此,在进行按位运算时,JS中大于32位的数字将趋于0,而C#始终采用较低的32位,因此结果为精确到那些32位(但不能表示更大的数字)。

  (2 + 2 ** 53) & (2 + 2 ** 53)  // 2
  (2 + 2 ** 54) & (2 + 2 ** 54) // 0

答案 3 :(得分:-2)

编辑(很抱歉以前的回答很差): 正如其他人之前所说,问题也与您的JS Number的大小有关。 如果您的代码在C#中工作,建议将功能转移到ASP.NET后端,该后端将通过某种API处理计算并转发结果