Consider that I need a n-sized vector where each element is defined between [-1,1]. The element a[i] is a float generated by -1 + 2*rand(). I need a elegant way to ensure that the sum of the elements of my array is equal to zero.
I've found two possible solutions:
The first one is this matlab function https://www.mathworks.com/matlabcentral/fileexchange/9700-random-vectors-with-fixed-sum. It has also a implementation in R, however it is too much work to implement it on C, since this function is used for a 2d array.
The second one is provided in this thread here: Generate random values with fixed sum in C++. Essentially, the idea is to generate n numbers with a normal distribution then normalize them to with my sum. (I have implemented it using python bellow) for a vector with sum up to 1.0. It works for every sum value except for zero.
import random as rd
mySum = 1;
randomVector = []
randomSum = 0
for i in range(7):
randomNumber = -1 + 2*rd.random()
randomVector.append(randomNumber)
randomSum += randomNumber
coef = mySum/randomSum
myNewList = [j * coef for j in randomVector]
newsum = sum(myNewList)
So, is there a way to do that using C or C++? If you know a already implemented function it would be awesome. Thanks.
I figured out a solution to your problem. This is not perfect since its randomness is limited by the range requirement.
The strategy is:
#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" );
}
}
I tried it, and it works also when n=1. In case of n=0 a sanity check should be added to my example.
Some output examples:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With