2015-04-14 3 views
0

Мне нужно было взять массив (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

В качестве дополнительной записке, ни один элемент никогда не должен быть равен 0. Кроме того, я использую элементы в качестве ограничителя в течение цикла, так как не нужно работать в 100 раз для массива в пять элементов, но 10 раз для массива из 1000 элементов, скорее всего, не будет рандомизировать слишком много. –

+2

Если у вас есть рабочий код и вы ищете улучшения, [CodeReview] (http://codereview.stackexchange.com/) может быть лучше, чем StackOverflow. – dcastro

+1

Это выглядит немного странным способом создания нового «Случайного». Но я согласен с @dcastro - возможно, лучше спросить об обзоре кода. –

ответ

0

Если я правильно все понял, задача требует суммы сохраняемых элементов. Тогда нет необходимости в значениях начальных элементов массива, две вещи, которые имеют значение, - это сумма элементов и количество элементов.

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

вместо '' '' '' int [] 'Я бы просто сделал его' double [] ', а затем называет' w [i] = rnd.NextDouble() ', который дает вам тот же вес от 0 до 100% (хотя scalled от 0 до 1 вместо 0 до 100) –

+0

@Scott Chamberlain Вы правы. Однако я не хотел работать с парными, поскольку они дают ошибку. Можно просто увеличить значение MAX в rnd.Next (0, MAX), не обращая внимания на аккумуляторы, а не на переполнение. Тип Int64 будет лучше для них. –

+0

@IvanGritsenko Спасибо за вышеуказанный код. Как абсолютно просто, я никогда не думал резервировать 1 для каждого элемента. Кроме того, весы - хороший способ решить проблему. Возможно, мне придется увидеть, какая общая скорость отличается, но я полагаю, что должна быть разумная польза от того, как работает ваш образец. –

Смежные вопросы