如何生成总计为0.0的n大小的随机浮点数组?

Tha*_*arl 6 c c++ arrays random

考虑到我需要一个n大小的矢量,其中每个元素都定义在[-1,1]之间。元素a [i]是由-1 + 2 * rand()生成的浮点数。我需要一种优雅的方法来确保数组元素的总和等于零。

我发现了两种可能的解决方案:

第一个是这个matlab函数https://www.mathworks.com/matlabcentral/fileexchange/9700-random-vectors-with-fixed-sum。它在R中也有一个实现,但是在C上实现它的工作量很大,因为此函数用于2d数组。

此线程在此处提供第二个在C ++中生成具有固定总和的随机值。本质上,这个想法是生成具有正态分布的n个数字,然后用我的总和将它们归一化。(我已经使用python波纹管实现了它),向量总计为1.0。它适用于除零以外的每个和值。

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)
Run Code Online (Sandbox Code Playgroud)

那么,有没有办法使用C或C ++做到这一点?如果您知道已经实现的功能,那就太好了。谢谢。

Rob*_*oni 2

我找到了解决你问题的方法。这并不完美,因为它的随机性受到范围要求的限制。

策略是:

  1. 定义一个能够生成可自定义范围内的随机浮点数的函数。无需重新发明轮子:我从/sf/answers/3087356261/借来的
  2. Malloc 数组(我在示例中省略了指针检查)并初始化种子。在我的示例中,我只使用了当前时间,但它可以改进
  3. 对于要生成的每个元素,预先计算随机范围。给定第 i 个和,确保下一个和永远不会超出范围:如果和为正,则范围需要为 (-1,1-sum);如果为负数,则范围需要为 (-1-sum,1)
  4. 这样做直到第 (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" );
        }
    }
Run Code Online (Sandbox Code Playgroud)

我尝试了一下,当n=1时也有效。如果 n=0,应将健全性检查添加到我的示例中。

一些输出示例:

N=1:

Input value: 1

  outArr[0]=-0.000000   (sum=-0.000000)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)