Показать сообщение отдельно
  #57 (permalink)  
Старый 31.07.2012, 22:55
Аватар для Дзен-трансгуманист
√₋̅₁̅
Отправить личное сообщение для Дзен-трансгуманист Посмотреть профиль Найти все сообщения от Дзен-трансгуманист
 
Регистрация: 18.06.2012
Сообщений: 385

Сообщение от oneguy
В задаче нужно сделать, чтоб каждая возможность выпадала с одинаковой вероятностью
O RLY?

Сообщение от leny
Необходимо написать функцию деления числа "A" на несколько случайных, сумма которых в итоге будет числом "A".
Во-первых, "на несколько случайных" != "с равным шансом на одну из всех возможных комбинаций"
Во-вторых, ничего не сказано о том, что последовательность имеет значение.

А поэтому:
Сообщение от oneguy
Не нужно подгонять распределение под ваше решение
- что в такой же степени касается и вас. Но по большому счету, пока ТС не озвучил способ распределения вероятностей - любое решение, удовлетворяющее исходным условиям, будет технически правильным.

Расходимость наших решений в том, что у вас количество возможных ситуаций внутри функции с учетом динамики их возникновения равно
(a - m*n + n-1)! / (a - m*n)!

а у меня
(a - m*n + 1)^(n-1) * (n-1)!

Поэтому у вас все комбинации равновероятны, а у меня нет.

А вот ваша последняя функция мне понравилась. Я тоже решил попробовать двоичный поиск и комбинаторику, чтобы сделать все комбинации равновероятными. И хотя, ради чистоты эксперимента, в вашу функцию я нарочно не подглядывал, но всё же наши решения оказались очень похожи. Сравнение буду делать только на двоичном поиске, поэтому первый алгоритм из вашей функции я намеренно удалил.

function divide (a, n, m) { // by oneguy

  if (n*m>a) return;

  var b=[], d=[], p=a-(m-1)*n-1;

  for (i=0; i<n-1; i++) {
    var c=Math.floor(Math.random()*(p-i));
    var x=0, y=i;
    while (x<y) {
      var t=Math.floor((x+y)/2);
      if (d[t]-t>c) y=t; else x=t+1;
    }
    d.splice(x, 0, c+x);
  }
  d.push(p);

  b.length=0; b[0]=d[0]+m;
  for (i=0; i<n-1; i++) b.push(d[i+1]-d[i]+m-1);
  return b;
}

function SplitNum2 (a, n, m) { // by Дзен-трансгуманист

  if (n < 1 || n * m > a) { return []; }
  if (n == 1) { return [a]; }

  var i, j, q = -1, w, e;
  var r = a - (m * n) + n - 1;
  var f = Math.floor(Math.random() * r);
  var p = [f], s = [];

  for (i=1; i<n-1; i++) {
    if (!(i & (i-1))) { q++; }
    j = Math.floor(Math.random() * (r-i));
    if (j < f) { f = j; p.unshift(j); continue; }
    w = 1 << q;
    e = w >> 1;
    while (e) {
      if (w > i || j+w <= p[w-1]) { w -= e; }
      else if (w == i || j+w < p[w]) { break; }
      else { w += e; }
      e >>= 1;
    }
    p.splice(w, 0, j+w);
  }
  p.push(r);

  s[0] = p[0] + m;
  for (i=1; i<n; i++) { s[i] = p[i] - p[i-1] + m - 1; }
  return s;
}

function testPerformance (a, n, m, iterations) {

  var i, j, fn, time1, time2;
  var fnarr = [ "divide", "SplitNum2" ];
  var result = "a = " + a + "; n = " + n + "; m = " + m + ";   ( " + iterations + "x )\n\n";

  function Now () { return (new Date()).getTime(); }

  for (i=0; i<fnarr.length; i++) {
    fn = eval(fnarr[i]);
    time1 = Now();
    for (j=0; j<iterations; j++) { fn(a, n, m); }
    time2 = Now();
    result += fnarr[i] + ": " + ((time2 - time1) / 1000).toFixed(3) + " sec.\n";
  }

  return result + "\n";
}

var text = "";
text += testPerformance(130, 3, 20, 10000);
text += testPerformance(130, 30, 0, 1000);
text += testPerformance(100, 4, 25, 10000);
text += testPerformance(1000, 1000, 0, 10);
text += testPerformance(1000000000, 10000, 0, 1);
alert(text);
__________________

Гейзенберг, возможно, читал этот тред.

Последний раз редактировалось Дзен-трансгуманист, 02.08.2012 в 01:10.
Ответить с цитированием