【问题标题】:Uniform Distribution: Bug or Paradox均匀分布:错误或悖论
【发布时间】:2021-10-27 15:04:47
【问题描述】:

假设有 10 辆汽车随机均匀分布在长度为 1 的圆形轨道上。如果位置由 [0,1> 范围内的 C double 表示,则可以对它们进行排序,汽车之间的间隙应该是位置前面汽车的位置减去后面汽车的位置。最后一个间隙需要加 1 来说明不连续性。

在程序输出中,最后一列的统计数据和分布与其他列非常不同。行正确添加到 1。发生了什么?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int compare (const void * a, const void * b)
{
  if (*(double*)a > *(double*)b) return 1;
  else if (*(double*)a < *(double*)b) return -1;
  else return 0;
}

double grand_f_0_1(){
  static FILE * fp = NULL;
  uint64_t bits;

  if(fp == NULL) fp = fopen("/dev/urandom", "r");
  fread(&bits, sizeof(bits), 1, fp);
  return (double)bits * 5.421010862427522170037264004349e-020; // https://stackoverflow.com/a/26867455
}

int main()
{
  const int n = 10;
  double values[n];
  double diffs[n];
  int i, j;
  
  for(j=0; j<10000; j++) {
  
    for(i=0; i<n; i++) values[i] = grand_f_0_1();

    qsort(values, n, sizeof(double), compare);
    
    for(i=0; i<(n-1); i++) diffs[i] = values[i+1] - values[i];
    diffs[n-1] = 1. + values[0] - values[n-1];

    for(i=0; i<n; i++) printf("%.5f%s", diffs[i], i<(n-1)?"\t":"\n");

  }
  
  return(0);
}

这是一个输出示例。第一列代表第一辆车和第二辆车之间的差距。最后一列代表第 10 辆车和第 1 辆车之间的距离,跨越起点/终点线。 .33 和 .51 等大数字在最后一列中更为常见,而非常小的数字则相对少见。

0.13906 0.14241 0.24139 0.29450 0.01387 0.07906 0.02905 0.03160 0.00945 0.01962
0.01826 0.36875 0.04377 0.05016 0.05939 0.02388 0.10363 0.04640 0.03538 0.25037
0.04496 0.05036 0.00536 0.03645 0.13741 0.00538 0.24632 0.04452 0.07750 0.35176
0.00271 0.15540 0.03399 0.05654 0.00815 0.01700 0.24275 0.25494 0.00206 0.22647
0.34420 0.03226 0.01573 0.08597 0.05616 0.00450 0.05940 0.09492 0.05545 0.25141
0.18968 0.34749 0.07375 0.01481 0.01027 0.00669 0.04306 0.00279 0.08349 0.22796
0.16135 0.02824 0.07965 0.11255 0.05570 0.05550 0.05575 0.05586 0.07156 0.32385
0.12799 0.18870 0.04153 0.16590 0.02079 0.06612 0.08455 0.14696 0.13088 0.02659
0.00810 0.06335 0.13014 0.06803 0.01878 0.10119 0.00199 0.06656 0.20922 0.33263
0.00715 0.03261 0.05779 0.47221 0.13998 0.11044 0.06397 0.00238 0.04157 0.07190
0.33703 0.02945 0.06164 0.01555 0.03444 0.14547 0.02342 0.03804 0.16088 0.15407
0.10912 0.14419 0.04340 0.09204 0.23033 0.09240 0.14530 0.00960 0.03412 0.09950
0.20165 0.09222 0.04268 0.17820 0.19159 0.02074 0.05634 0.00237 0.09559 0.11863
0.09296 0.01148 0.20442 0.07070 0.05221 0.04591 0.08455 0.25799 0.01417 0.16561
0.08846 0.07075 0.03732 0.11721 0.03095 0.24329 0.06630 0.06655 0.08060 0.19857
0.06225 0.10971 0.10978 0.01369 0.13479 0.17539 0.17540 0.02690 0.00464 0.18744
0.09431 0.10851 0.05079 0.07846 0.00162 0.00463 0.06533 0.18752 0.30896 0.09986
0.23214 0.11937 0.10215 0.04040 0.02876 0.00979 0.02443 0.21859 0.15627 0.06811
0.04522 0.07920 0.02432 0.01949 0.03837 0.10967 0.11123 0.01490 0.03846 0.51915
0.13486 0.02961 0.00818 0.11947 0.17204 0.08967 0.09767 0.03349 0.08077 0.23426

【问题讨论】:

  • 您不能使用double“均匀分布”0到1范围内的10个项目。请参阅Is floating point math broken?Why Are Floating Point Numbers Inaccurate?
  • 最后一列是两个随机数相加的结果,所以它有不同的分布。具体来说,它将具有与掷两个骰子相同的三角形分布。
  • 尝试2而不是10辆车。1号车的平均位置将是0.33;汽车 2 0.66。一个区别是另一个的两倍。
  • 请打印每列的估计平均值和方差。
  • @WeatherVane "你不能使用double"均匀分布" 0 到 1 范围内的 10 个项目" -- 当然可以,比你更精确可能需要。当然,浮点不能准确地表示所有实数值,double 的精度在 0.0 到 1.0 的范围内变化很大,但在最坏的情况下,它通常会精确到大约 15 个十进制数字。从uint64_tdouble 的转换会丢失一些数字,但对于这个程序来说还不够重要。

标签: c debugging random paradox uniform-distribution


【解决方案1】:

您的代码没问题。最后一个差的平均值是其他差的两倍。

悖论来自这样一个事实,而不是在一个单位区间上选择 10 个点,而是实际上试图将其划分为 11 个子区间,并进行 10 次切割。因此,每个子区间的预期长度为 1/11。

连续点之间的差异接近 1/11,除了最后一对,因为它包含最后一个子区间(在最后一个点和点 1 之间)和第一个子区间(在点 0 和第一个点之间)。

因此最后一个差异的平均值是 2/11。

【讨论】:

  • 我认为这很接近。如何生成 10 辆汽车的 [0,1> 位置,以便所有位置均等可能被占用,并且所有间隙在统计上都模糊不清?
  • 我想将第一个点固定为 0,随机选择剩余 9 个,排序并最终将 所有 个点按随机数移动即可完成工作。
  • 我试过了(加上换班后的额外位置),最后一个差距仍然是其他差距的两倍。见gist.github.com/alwynallan/2f6d9fd125a7653dbd8d7217cafe275d
  • @APA:仅在排序后移位,仅排序一次。在计算diffs(从0n)时,如果它是负数,则添加1.0
  • 如果你想让值保持在相同的顺序并且在01之间,移动不超过1 - values[9](当然是在排序之后):-)
【解决方案2】:

“圆上没有特殊点”

问题是,在一个圆圈上,一辆车看起来总是一样的,所以没有必要与零相关:你可以只与第一辆车相关。这意味着您可以将第一辆车固定为零,并将其他汽车的随机位置视为与它相关(从它测量)。

因此,方便的解决方案是将第一辆车固定为零,并将您仍然生成的 9 个数字视为与第一辆车相关的位置。

希望这是一个令人满意的答案:-)

IDENTITY(或哪个差异在前?)

如果将 10 辆带有标签(“1”、“2”等)的汽车随机放置在一个圆圈上,则从“1”到下一个的差值平均为 1/10。 排序时,第一个差异 “失去了它的身份”它发生了什么变化:类似于选择第一个差异为最长的差异,它会平均更多。根据汽车与零偏差(或者,更准确地说:变化)的关系以类似的方式选择它。

第一个差异(第 2、第 3 等)只是变得不同了——将其定义为与给定汽车的差异更直观,并提供了将其用作参考的选项(与圆形对称完美搭配);其余汽车相对于它的分布是统一的。处理最小的随机点并不是那么简单。

总结:定义你正在计算的内容,知道你的定义和概率是非直观的

【讨论】:

  • 我给了这个和其他答案一样的赞成票。它更接近于原始代码未正确建模间隙的直观原因。
  • 谢谢!概率往往不是以一种真正独特的方式直观的。
【解决方案3】:

经过 3 个月的困惑,我有了一个直观的解释,至少对我来说是这样。这是@wojand 和@tstanisl 提供的答案的累积。

我的原始代码是正确的:它在区间上均匀分布点,所有点的前向差异具有相同的统计分布。矛盾的是,最高值点的前向差异,即跨越 0-1 不连续点的点,平均是其他点的两倍,并且它的分布具有不同的形状。

这种前向差异具有不同分布的原因是它包含值 0。较大的前向差异(差距)更有可能包含任何固定值,仅仅是因为它们更大。

例如,我们可以搜索包含 1/pi 的间隙,它也将具有相同的非典型分布。

【讨论】:

    猜你喜欢
    • 2011-04-04
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 2019-02-21
    • 2016-08-07
    • 1970-01-01
    相关资源
    最近更新 更多