【发布时间】: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;汽车 20.66。一个区别是另一个的两倍。 -
请打印每列的估计平均值和方差。
-
@WeatherVane "你不能使用
double"均匀分布" 0 到 1 范围内的 10 个项目" -- 当然可以,比你更精确可能需要。当然,浮点不能准确地表示所有实数值,double的精度在 0.0 到 1.0 的范围内变化很大,但在最坏的情况下,它通常会精确到大约 15 个十进制数字。从uint64_t到double的转换会丢失一些数字,但对于这个程序来说还不够重要。
标签: c debugging random paradox uniform-distribution