生成均匀分布的随机噪声

时间:2010-09-12 21:37:05

标签: algorithm language-agnostic statistics distribution

我一直在努力为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)。这在生成我的地图时效果不佳,因为我需要确定填充地图的百分比。我也不能使用直方图来确定要使用的阈值,因为我按需生成方块,而不是整个地图。

我需要在两个点上进行均匀分布 - 在插值之后,以及在噪声函数求和之后。我不知道该怎么做,所以。

我的发行版如下:

Normal distribution

我需要它看起来像这样:

Uniform distribution

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

任何解决方案都很受欢迎,但我用C#编写,因此代码片段非常有用。

3 个答案:

答案 0 :(得分:2)

将得到的样本与高斯的CDF合并,即0.5 * erf(x)+ 1(erf =误差函数)。

请注意,根据中心极限定理,无论何时计算随机变量的总和,都会得到高斯定律。

答案 1 :(得分:1)

这是对您最终评论的回答,而不是您提出的问题。我不一定认为你可以将你的结果分布扩展回统一分布,我不确定你是否愿意。但是,如果您的目标是将所有50%以下的值变为草,那么测量(或估计)输出中值可能更容易且更不容易出错,并将其称为50%。

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

答案 2 :(得分:0)

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

你有一句话:

       |   /
     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

附加说明:

我正在做的假设 - 线 - 交叉零件因为我经验丰富的眼睛告诉我这是正确的。但如果我在高中数学考试中这样做,我可能会失去学分(即使我的答案是正确的)。对于正确的公式解决方案,要查找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));