Javascript - 这个噪音功能会起作用吗?

问题描述 投票:0回答:4

我有一个确定性的噪声函数,我已经在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中使用,如果这不起作用?

javascript random noise
4个回答
1
投票

根本问题是,在javascript中,没有整数 - 所以所有数学函数都是使用Number(52位精度浮点数)完成的

在c#中,如果你使用long,那么任何溢出都会被丢弃

在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#产生的确切内容,你可能需要使用它


0
投票

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


0
投票

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

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

-2
投票

编辑(对不起之前的答案感到抱歉):正如其他人之前所说的那样,问题也与您的超出JS编号大小的值有关。如果您的代码在C#中工作,那么建议将功能卸载到ASP.NET后端,后端将通过某种API处理计算结果。

© www.soinside.com 2019 - 2024. All rights reserved.