生成遵循特定分布的随机双精度

  • 本文关键字:分布 随机 双精度 c
  • 更新时间 :
  • 英文 :


所以我有分布f(x) = (4-2x)/3,用于[0,1]xf(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 …

我有两个问题:

  1. 我错过了什么?
  2. 在我提供的链接中,他为什么用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.px相同,但出于某种原因,他们添加了额外的 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 的积分是 (4xx2(/3(加上一个常数(。由于在x=0 时为零,而f(x( 对于 x <0 为零,因此 F(x( 在 [0, 1] 中也是 (4xx2(/3。

如果我们有一个来自 [0, 1] 中均匀分布的样本 p,则点 x 在 x 或以下的所需分布量等于 p 或低于 p 的均匀分布量满足 F(x( =p

因此 (4xx2(/3 = p,所以x=2+ sqrt(4−3p(。

因此,给定用p = (double) rand() / RAND_MAX生成的p,我们可以找到所需分布的样本为2 + sqrt(4-3*p)

最新更新