我找到了解决你问题的办法。这并不完美,因为它随机性受范围要求的限制。
策略是:
- 定义一个能够生成可自定义范围内的随机浮点数的函数。无需重新发明轮子:我借用了https://stackoverflow.com/a/44105089/11336762 https://stackoverflow.com/a/44105089/11336762
- Malloc 数组(我在示例中省略了指针检查)并初始化种子。在我的示例中,我只使用了当前时间,但它可以改进
- 对于要生成的每个元素,预先计算随机范围。给定第 i 个和,确保下一个和永远不会超出范围:如果和为正,则范围需要为 (-1,1-sum);如果为负数,则范围需要为 (-1-sum,1)
- 这样做直到第 (n-1) 个元素。最后一个元素必须直接赋值为改变符号的和。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
float float_rand( float min, float max )
{
float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
return min + scale * ( max - min ); /* [min, max] */
}
void main( int argc, char *argv[] )
{
if( argc == 2 )
{
int i, n = atoi ( argv[1] );
float *outArr = malloc( n * sizeof( float ) );
float sum = 0;
printf( "Input value: %d\n\n", n );
/* Initialize seed */
srand ( time( NULL ) );
for( i=0; i<n-1; i++ )
{
/* Limit random generation range in order to make sure the next sum is *
* not outside (-1,1) range. */
float min = (sum<0? -1-sum : -1);
float max = (sum>0? 1-sum : 1);
outArr[i] = float_rand( min, max );
sum += outArr[i];
}
/* Set last array element */
outArr[n-1] = -sum;
/* Print results */
sum=0;
for( i=0; i<n; i++ )
{
sum += outArr[i];
printf( " outArr[%d]=%f \t(sum=%f)\n", i, outArr[i], sum );
}
free( outArr );
}
else
{
printf( "Only a parameter allowed (integer N)\n" );
}
}
我试了一下,n=1的时候也可以。如果 n=0,应将健全性检查添加到我的示例中。
一些输出示例:
N=1:
Input value: 1
outArr[0]=-0.000000 (sum=-0.000000)
N=4
Input value: 4
outArr[0]=-0.804071 (sum=-0.804071)
outArr[1]=0.810685 (sum=0.006614)
outArr[2]=-0.353444 (sum=-0.346830)
outArr[3]=0.346830 (sum=0.000000)
N=8:
Input value: 8
outArr[0]=-0.791314 (sum=-0.791314)
outArr[1]=0.800182 (sum=0.008867)
outArr[2]=-0.571293 (sum=-0.562426)
outArr[3]=0.293300 (sum=-0.269126)
outArr[4]=-0.082886 (sum=-0.352012)
outArr[5]=0.818639 (sum=0.466628)
outArr[6]=-0.301473 (sum=0.165155)
outArr[7]=-0.165155 (sum=0.000000)