所以我有分布f(x) = (4-2x)/3
,用于[0,1]
x
,f(x) = 0
其他地方。
我现在想从这个分布中生成 n = 100 个随机数。我尝试遵循此示例,这是我自己的代码:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <math.h>
#include <stdlib.h>
//pdf(x) = 1 if x>1
// = 0 if x<0
// = 1/3*(4-2x) otherwise
int N = 10;
int var1(int argc, char **argv) {
int p = 0, i;
for (i = 0; i < N; i++) {
p = (double)(rand() % 100)/100; // Generates 100 numbers in [0,1]
if (p > 1)
printf("%d ", 0);
else if (p < 0)
printf("%d ", 0);
else
printf("%f ", p * (4-2*0.1)/3);
}
printf("...");
return 0;
}
但是我的输出只是零:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 …
我有两个问题:
- 我错过了什么?
- 在我提供的链接中,他为什么用
0.1
替换x
?我只是做了同样的事情,但我不明白为什么。
首先,您没有返回您认为的随机数范围:
p = (double)(rand() % 100)/100;
右手尺寸将为您提供(0.00,0.01,0.02 ...0.99 (. 但是你把这个值分配给p
,它的类型是int
。 小数部分将被截断,因此分配的值将始终为 0。
将p
类型更改为double
以存储正确的值。 此外,如果您想要更大范围的随机值,请改用以下内容:
p = (double)rand() / RAND_MAX;
至于这个:
printf("%f ", p * (4-2*0.1)/3);
与链接代码相比:
printf("%f ", p * 0.1 / 360);
他们的代码没有用 0.1 代替x
.p
与x
相同,但出于某种原因,他们添加了额外的 0.1 因子。
为了让你做f(x) = (4-2x)/3
,你需要这个:
printf("%f ", (4-2*p)/3);
前言
问题中的函数 f(x( = (4-2 x(/3 对于 [0, 1]中的x是概率密度函数,而不是累积分布函数。如果将分布绘制为在 x 轴和曲线之间具有单位面积的曲线,则概率密度函数是该曲线的斜率,而累积分布函数是曲线下直到某个x的面积量。
我们可以看到 (4-2x(/3 不是累积分布函数,因为累积分布在分布结束时必须是 1(一般来说∞,但这里是 1,因为函数在 1 以上为零,但 (4-2x(/3 在 1 时是 2/3。我们可以看到它是一个概率密度函数,因为它的积分(如下所示(在分布结束时为 1。
问题中给出的链接使用累积分布函数。实际上,它是 [0, 360] 上均匀分布的累积分布函数。正因为如此,求解必要的方程(见下文(只是一个缩放问题。这是微不足道的,不能作为为任意分布生成样本的一般示例。
溶液
给定一个概率密度函数 f(x(,相应的累积分布函数 F(x( 是 f 从 −∞ 到x的积分。我们可以使用累积分布函数将均匀分布转换为所需的分布。
(4-2x(/3 的积分是 (4x−x2(/3(加上一个常数(。由于在x=0 时为零,而f(x( 对于 x <0 为零,因此 F(x( 在 [0, 1] 中也是 (4x−x2(/3。
如果我们有一个来自 [0, 1] 中均匀分布的样本 p,则点 x 在 x 或以下的所需分布量等于 p 或低于 p 的均匀分布量满足 F(x( =p。
因此 (4x−x2(/3 = p,所以x=2+ sqrt(4−3p(。
因此,给定用p = (double) rand() / RAND_MAX
生成的p,我们可以找到所需分布的样本为2 + sqrt(4-3*p)
。