【问题标题】:Generation of uniformly distributed random noise产生均匀分布的随机噪声
【发布时间】:2010-09-12 21:37:05
【问题描述】:

我一直在为我的map generator 生成 Perlin 噪声。我遇到的问题是随机噪声不是正态分布的,更可能是各种正态分布。

给定两个整数 X 和 Y,以及一个种子值,我执行以下操作:

  • 使用MurmurHash2 生成随机数(-1,1)。这是均匀分布的。
  • 使用三次插值在整数值之间插入点。值现在落在范围 (-2.25, 2.25) 内,因为插值可以在相似值之间外推更高的点(每个维度增加 1.5),并且分布不再均匀。
  • 生成这些插值点,将它们加在一起,同时将幅度减半(请参阅:Perling noise)随着和的数量接近无穷大,范围的限制现在接近先前值的两倍,或 (-4.5, 4.5) 和现在更不统一了。

当我想要 (-1, 1) 的范围时,这显然不起作用,因此我将所有最终值除以 4.5。实际上,我一直将它们除以(在对每个维度进行插值后除以 1.5,然后在对噪声求和后除以 2。)

除法后,我的理论范围为 (-1, 1)。但是,绝大多数值是 (-0.2,0.2)。这在生成我的地图时效果不佳,因为我需要确定地图填充的百分比。我也无法使用直方图来确定要使用的阈值,因为我是按需生成正方形,而不是整个地图。

我需要使我的分布在两点均匀 - 插值之后,以及噪声函数的总和之后。我不知道该怎么做。

我的分布如下所示:

我需要它看起来像这样:

(两张图片均来自维基百科。)

感谢任何解决方案,但我是用 C# 编写的,所以代码 sn-ps 将非常有帮助。

【问题讨论】:

  • 抱歉,我没有完全理解您的问题:您希望有人帮助您调试您的算法,还是 Normal[mu,sigma] 随机数生成器?
  • 不,我的算法工作正常,只是不是我想要的。而且我不想生成随机正态分布。我想采用我的算法,该算法生成随机正态分布(-4.5,4.5)并使其生成均匀分布(-1,1)。
  • 您在第 1 步已经有了一个统一的 (-1,1) 分布...
  • @Keith - 是的,但我没有 Perlin 噪声函数。只是完全随机的噪声,在产生自然团块等方面是无用的(见第一个链接。)
  • 所以您希望最终 Perlin 噪声形函数中的各个“点”具有随机分布而不是正态分布?并且在仍然拥有柏林形状的地图的同时做到这一点?

标签: algorithm language-agnostic statistics distribution


【解决方案1】:

将生成的样本与高斯的 CDF 相结合,即 0.5*erf(x) + 1(erf = 误差函数)。

请注意,根据中心极限定理,只要对随机变量求和,就会得到高斯定律。

【讨论】:

  • 我认为这是正确的答案,但我在想出错误函数时遇到了麻烦。平均值显然为零,​​但我如何确定方差?我知道我的分布的中间 50% 介于 (-.4,4) 之间,最大值为 1.672,最小值为 -1.734(在抽取十亿个样本后计算。)
  • cdf = 0.5 + 0.5 * erf((x - mu) / (sqrt(2 * variance)))。您必须根据经验确定方差(谷歌经验方差估计器)
【解决方案2】:

这是对您最终评论的回答,而不是您提出的问题。我不一定认为您可以将生成的分布重新调整为均匀分布,而且我不确定您是否愿意。但是,如果您的目标是让所有低于 50% 的值都成为草,那么测量(或估计)输出的中值并将其称为 50% 可能更容易且不易出错。

结果是一样的,您不必处理任何复杂(因此容易出错)的缩放函数。

【讨论】:

    【解决方案3】:

    这是一个简单的缩放问题。而所有简单的缩放问题都只是笛卡尔几何中直线的表现:

    你有一条线:

           |   /
         1 + -/,
           | / ,
    ____,__|/__,____
     -4.5 /|   4.5
        ,/ |
        /- + -1
       /   |
    

    在那条线上,当 x=4.5,y=1 和当 x=-4.5 时,y=-1。现在我敢肯定,一旦你意识到这一点,你就会知道解决方案。 y=mx + c。由于该线在正负两侧都是对称的,因此您可以假设它在零处相交,因此c=0。现在寻找斜率:

    m = dy/dx
    m = (1 - -1)/(4.5 - -4.5)
    m = 2/9
    

    因此:

    y = 2/9 x + 0
    y = 2x / 9
    

    所以,现在你可以插入了。当 x = 3 时,y 是多少?:

    y = 2*3 / 9
    y = 6/9
    y = 2/3
    

    当 x = 4 时 y 是多少?:

    y = 2*4 / 9
    y = 8/9
    

    补充说明:

    我正在做的假设-the-line-crosses-at-zero 的事情是因为我经验丰富的眼睛告诉我这是正确的。但是如果我这样做是为了高中数学考试,我可能会失去学分(即使我的答案是正确的)。对于正确公式解决方案,要找到c,您必须首先找到m,然后替换已知坐标的xy 值:

    y = 2/9 x + c
    

    鉴于 (4.5,1) 和 (-4.5,-1) 是已知坐标,用 x 和 y 代替 4.5 和 1:

    1 = 2*4.5/9 + c
    1 = 9/9 + c
    1 = 1 + c
    c = 1 - 1
    c = 0
    

    所有这些都可以体现在缩放函数中:

    // example code in javascript:
    function makeScaler (x1, y1, x2, y2) {
        var m = (x2-x1)/(y2-y1);
        var c = y1 - m*x1;
    
        // return a scaling function:
        return function (x) {
            return m*x + c;
        }
    }
    
    var f = makeScaler(-4.5,-1,4.5,1);
    alert(f(4)); // what y is when x is 4
    
    // or if you prefer:
    var g = makeScaler(-4.5,0,4.5,1); // scale from 0 to 1
    alert(g(4));
    

    【讨论】:

    • 这不能回答我的问题。如果分布已经均匀(一条直线),那么我就不会有问题了。我正在尝试将一条曲线强加到一条直线上。
    • @Daniel 您正在寻找的转换图片可能很有用
    • @belisarius - 我实际上不确定如何获得分布图。基本上,我只是在寻找一种将正态分布缩放为均匀分布的方法。
    • 这回答了你的问题。直线不是分布而是映射。映射是线性的。
    • 在你拒绝相信我的正确答案之前,让我们试试这个:生成分发并将其转储到文件中。然后应用线性映射函数并将其转储到另一个文件。绘制它。您将看到原始分布和线性缩放分布是相同的,除了被缩放的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 2011-08-08
    • 2021-07-23
    • 1970-01-01
    • 2021-12-28
    • 2012-03-21
    相关资源
    最近更新 更多