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

问题描述 投票:4回答:1

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

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

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

此线程在此处提供第二个:Generate random values with fixed sum in 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)

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

c++ c arrays random
1个回答
0
投票

我想出了解决您问题的方法。这不是完美的,因为其randomness受范围要求的限制。

策略是:

  1. 定义一个能够在可定制范围内生成随机浮点的函数。无需重新发明轮子:我从https://stackoverflow.com/a/44105089/11336762
  2. 着陆了
  3. Malloc数组(在我的示例中,省略了指针检查)并初始化种子。在我的示例中,我只是使用了当前时间,但可以改进]
  4. 对于要生成的每个元素,请预先计算随机范围。给定第i个和,请确保下一个和永远不会超出范围:如果和为正,则范围应为(-1,1-sum);如果为负,则范围必须为(-1-sum,1)
  5. 执行此操作直到第(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)
© www.soinside.com 2019 - 2024. All rights reserved.