简体   繁体   中英

Is There A Better Way to Add Entropy to Array of Ints?

I needed to take an array of (C#) integers and randomly reassign values to make the values "feel" more randomized, without changing the length or sum of the array. But this array can get quite large, so I'm wondering if anyone has a better way to do this. Basically, the array initially contains values that are roughly the sum divided by the length, with one element having the remainder. What I am using now is:

    static int[] AddEntropy(int[] ia)
    {

        int elements = ia.Length;
        int sum = ia.Sum();

        for (int runs = 0; runs < (elements * 2); runs++)
        {

            Random rnd = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), System.Globalization.NumberStyles.HexNumber));
            int rndi = rnd.Next(0, (sum / elements));
            int rnde1 = rnd.Next(0, elements);
            int rnde2 = rnd.Next(0, elements);
            if (rndi < 1 ) rndi = 1;

            if (ia[rnde1] > (rndi + 2))
            {
                ia[rnde1] = ia[rnde1] - rndi;
                ia[rnde2] = ia[rnde2] + rndi;
            }

        }

        return ia;
    }

Any thoughts on making this perform better would be appreciated. It seems to perform "well", but if the array are larger than my sample of five elements (up to 1000 elements), and there are several arrays that may be modified in quick succession, a speedier option would be great.

If I understood everything correctly the task requires the sum of the elements to be preserved. Then there is no need in initial array elements values, the two thing that matter are the sum of the elements and the number of the elements.

public static int[] GetArray(int sum, int n)
{
    if(sum < n)
        throw new ArgumentException("sum is lower than n");
    Random rnd = new Random();

    // reserve 1 for each of the elements
    sum -= n;

    // generate random weights for every element in sum
    int[] w = new int[n];
    int sw = 0;             
    for (int i = 0; i < n; i++)
    {
        w[i] = rnd.Next(0, 100);
        sw += w[i];
    }

    // generate element values based on their weights
    int[] result = new int[n];
    int tsum = 0;
    int psum = 0;
    for (int i = 0; i < n; i++)
    {
        tsum += w[i] * sum;
        result[i] = tsum / sw - psum;
        psum += result[i];
    }

    // restore reserved ones
    for (int i = 0; i < n; i++)
        result[i]++;

    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM