【问题标题】:Is There A Better Way to Add Entropy to Array of Ints?是否有更好的方法将熵添加到整数数组?
【发布时间】:2015-04-15 02:28:16
【问题描述】:

我需要获取一个 (C#) 整数数组并随机重新分配值,以使值“感觉”更随机,而无需更改数组的长度或总和。但是这个数组可能会变得很大,所以我想知道是否有人有更好的方法来做到这一点。基本上,数组最初包含的值大致是总和除以长度,一个元素具有余数。我现在使用的是:

    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;
    }

如果您有任何关于使其表现更好的想法,我们将不胜感激。它似乎表现“不错”,但如果数组大于我的五个元素(最多 1000 个元素)的样本,并且有几个数组可以快速连续修改,那么更快的选择会很棒。

【问题讨论】:

  • 作为附加说明,任何元素都不应该为 0。此外,我在 for 循环中使用元素作为限制器,因为它不需要为五元素数组运行 100 次,但是对于 1000 个元素的数组来说 10 次不太可能随机化太多。
  • 如果您有工作代码并且正在寻求改进,CodeReview 可能比 StackOverflow 更适合。
  • 这看起来有点奇怪创建一个新的Random。但我同意@dcastro - 可能最好在 Code Review 上提问。
  • ia.OrderBy(i =&gt; rnd.Next()).ToArray() 简单一百倍,对于大多数用途来说可能足够快,试一试。
  • @JesseWilliams 默认种子非常好,除非a)Random 的实例正在快速连续创建(如果rnd 移动到外部范围,则不会发生)或b)存在安全隐患,在这种情况下,您可能需要dedicated hardware。祝你好运

标签: c# arrays entropy


【解决方案1】:

如果我正确理解了所有内容,则任务需要保留元素的总和。那么初始数组元素值就不需要了,重要的两件事是元素的总和和元素的数量。

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;
}

【讨论】:

  • 而不是让w 成为int[],我只需将其设为double[],然后调用w[i] = rnd.NextDouble(),它会为您提供相同的 0 到 100% 权重(尽管称为 0 到 1而不是 0 到 100)
  • @Scott Chamberlain 你是对的。但是我不想使用双打,因为它们会出错。可以只增加 rnd.Next(0, MAX) 中的 MAX 值,同时注意累加器不会溢出。 Int64 类型对他们来说会更好。
  • @IvanGritsenko 感谢您提供上述代码。尽管它绝对简单,但我从未想过为每个元素保留 1。此外,权重是解决问题的好方法。我可能需要看看整体速度有何不同,但我认为您的样本运行方式应该有合理的好处。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多