« 1 2 »
Autor Zpráva
peta
Profil
Moderátor Chamurappi: Vytrženo z Jquery pannel gallery.

http://stackoverflow.com/questions/4205166/showing-random-divs-using-jquery
$("#container").html($("#container img").get().sort(function(){return 0.66 - Math.random();}));
Teoreticky by je to melo seradit nahodne, ale na disku mi stridal jen. Mozna je to tim, ze mi ulozil 2 v html :)
Witiko
Profil
peta:
Mohl bys nám méně osvíceným prozradit, co má znamenat těch 0.66 v function(){return 0.66 - Math.random();} nebo to máme nazývat petovou konstantou?
Witiko
Profil
Za Math.random() se skrývá standardní generátor pseudonáhodných čísel navracející číslice v intervalu <0; 1), přičemž poměr 50:50 je zajištěn zaokrouhlením 0.5 směrem vzhůru k nebesům. Pokud tedy chceš mít skutečnou shuffle funkci, pak potřebuješ něco takového:
function shuffle() {
  return Math.random() - 0.5;
}
Chamurappi
Profil
Reaguji na Witika:
skutečnou shuffle funkci“ … „return Math.random() - 0.5;
Také jsem žil mnoho let v této sladké nevědomosti :-)


Reaguji na peta:
Netvrdil jsi mi náhodou, že se stáhneš zpátky do Názorů na stránku?
JindraK
Profil *
ještě pořád mluvíte česky? :)
peta
Profil
Chamurappi:
Tak "ži"j "mnoho let v této sladké nevědomosti :-)"
Jo, silne to omezim, myslim, ze je to ale OT se o tom tady vykecavat.

JindraK, Witiko:
random = "obrázky přehrávalo náhodně"
shuffle = zamichat
Math.random() - 0.5 nebo 0.5 - Math.random() = nahodne cislo v intervalu [-0.5, +0.5]
0.66 - Math.random() = nahodne cislo v intervalu [-0.33. 0.66]
sort = serazeni pole, coz je neco jineho jako nahodne rozmisteni (mozna by bylo lepsi indexu pole priradit nahodne cislo a toho nove pole pak seradit beznym sortem)
"ale na disku mi stridal jen" = ...jen dva :) Jsem totiz ulozil tu stranku na disk a pridal k tomu js, jenze obrazky to nejak zobrazuje jen dva.

Pokud das na pas vedle sebe 6 fotek a pouzijes serazeni random 1:1 (50:50), tak dojde k tomu, ze ti pulku nepromicha. Proto jsem zvolil pomer napriklad 2:3. Neni na tom treba nic vysvetlovat, je to logicke, pokud chapes, jak ten algoritmus pracuje. Tak jsem to ani nerozvadel. Jindra je stejne liny cokoliv studovat a priste napise pozadavek do prace a zakazky a zada sumicku jako odmenu. Witiko je zas linej chapat sirsi souvislosti a tez se neorientuje v tom, kdyz to rozkecam. Takze jsem to tentokrat nerozkecaval. Za coz mi je pro zmenu vdecny Chamurappi, ze to nemusi cist, protoze se snazim diskutovat o vsem moznem a jeho predstava fora je mit tu jen faq, otazka, odpoved a ostatni je spam. Otevrenou diskuzi nebere.
_es
Profil
peta:
sort = serazeni pole, coz je neco jineho jako nahodne rozmisteni
Mohol by si vysvetliť, v čom je náhodné zoradenie prvkov poľa principiálne odlišné od náhodného rozmiestnenia prvkov poľa?

Pokud das na pas vedle sebe 6 fotek a pouzijes serazeni random 1:1 (50:50), tak dojde k tomu, ze ti pulku nepromicha. Proto jsem zvolil pomer napriklad 2:3. Neni na tom treba nic vysvetlovat, je to logicke, pokud chapes, jak ten algoritmus pracuje.
To je nejaký nezmysel. Číslo predstavuje len to, ktorý prvok má byť v poradí skôr, teda ak to polovicu nepremieša, tak je príčinou zle zvolený samotný algoritmus, nie nejaká zle zvolená optimalizačná „petova konštanta“.

Ak by programátori MS čítali internetové diskusie, asi by nespravili takúto chybu:-)
peta
Profil
_es: Vyzkousej to. Porovname pak vysledky.
_es
Profil
peta:
Vyzkousej to.
Nepotrebujem nič skúšať, matematika zo stredoškolského vzdelania mi stačí na to, aby som vedel, že že ak tá tvoja „optimalizovaná“ funkcia vracia pseudonáhodné číslo v intervale (-0,34; 0.66>, tak bude zoradenie menej náhodné, ako keď vracia pseudonáhodné číslo v intervale <-0,5; 0,5). Zle zvolený algoritmus by sa dal vylepšiť napríklad jeho mnohonásobným aplikovaním, lepšie je však použiť správny algoritmus.
Witiko
Profil
peta:
Pokud das na pas vedle sebe 6 fotek a pouzijes serazeni random 1:1 (50:50), tak dojde k tomu, ze ti pulku nepromicha.
[1,2,3,4,5,6].sort(function() {return Math.random() - 0.5;}); => [3,1,6,5,2,4] - Vážně?

Proto jsem zvolil pomer napriklad 2:3
Jediné, čeho tím dosáhneš je, že funkce bude navracet kladná čísla s dvakrát takovou četností. Tzn. výsledek se bude více blížit [6,5,4,3,2,1] než skutečné náhodě.

Zajímavější je ale již výše zmíněné téma - algoritmus na třídění pole je totiž závislý na implementaci a díky náhodnému vyhazování čísel může detekovat nekonzistentní navracené výsledky. (Např. A > B, A < C, ale C < B) Výsledek proto není zaručen - algoritmus může pole ponechat v původním nezměněném formátu nebo změnit jen část. Implementoval jsem proto náhodný shuffle podle Fisher-Yatesova algoritmu zmiňovaného na stackoverflow diskuzi odkázané ve zmíněném tématu. Obecná definice vypadá nějak takto:
Array.prototype.shuffle = function() {
  var i = this.length - 1, j, temp;
  while(i) {
    temp = this[i];
    this[i] = this[(j = Math.round(i-- * Math.random()))];
    this[j] = temp;
  }
};

Chamurappi ... Otevrenou diskuzi nebere.
Jindra je stejne liny
Witiko je zas linej chapat
A pak je tu peta, který je zase líný obtěžovat se s háčky a čárkami, jelikož brzdí jeho nezdolného génia. Ale který mě především inspiruje k návrhu nového pravidla inspirovaného Wikipedií a sice - Žádný vlastní výzkum. Pokud tvrdím, že to, co předkládám, je pravda, pak to doložím příslušnou referencí. Ne, že sem napíšu svou kosmologickou konstantu 0.66 a na ostatní shlížím jako na idioty, kteří nedosáhli vyšší úrovně poznání.
_es
Profil
Witiko:
Pokud má někdo ve své používané sadě funkcí metodu Array.prototype.swap(z, do), tak si může zápis ještě zkrátit. Osobně to implementuji takto:
Tipujem, že je v tejto implementácii nejaký zádrheľ.

Nestačí vyjsť pri tej implementácii napríklad z tohoto?
Witiko
Profil
_es:
Tipujem, že je v tejto implementácii nejaký zádrheľ.
Zádrhel v ní není, funguje bravurně a je založená na Fisher-Yatesovu algoritmu, viz. pseudokód:
for i from n − 1 downto 1 do
  j random integer with 0 ≤ j ≤ i
  exchange a[j] and a[i]

Ukázka:
var a = [1, 2, 3, 4, 5, 6]; a.shuffle(); // a obsahuje [5, 1, 2, 6, 4, 3] - použit kód z [#10].
K napsání toho kódu mě inspiroval právě ten tvůj příspěvek, protože tebou zveřejněný algoritmus mi přišel zbytečně složitý.
_es
Profil
Witiko:
Zádrhel v ní není, funguje bravurně
Síce funguje, no zle.
Pri náhodnom zoradení prvkov poľa [0,1,2,3,4] milión krát a sčítaní na rovnakej pozícii mi vyšlo:
1955498,1951232,2049892,2042749,2000629
pričom by mali vyjsť čísla málo sa líšiace od:
2000000,2000000,2000000,2000000,2000000
Witiko
Profil
_es:
A já jsem udělal to samé několikrát a vyšlo mi:
2001631, 1999430, 1998405, 2000259, 2000275
2000607, 2000418, 1998391, 2000376, 2000208
1999168, 1999922, 1998967, 2000752, 2001191

Když jsem stejným způsobem spočítal z milionu volání průměrný index s největším číslem, vyšlo mi:
2.000178, 1.998943, 1.999991, 2.000688 - středem je skutečně 2

Tzn. nezdá se mi, že by zde byl bias pro určité indexy. Spíš se tedy přikláním k tomu, že milion je nereprezentativní vzorek a algoritmus funguje tak, jak má.
_es
Profil
Witiko:
A já jsem udělal to samé a vyšlo mi
Asi to závisí od prehliadača, mne vo FF 6.0.2 vychádzajú opakovane podobné čísla, aj v Opere.
Witiko
Profil
_es:
Je nepravděpodobné, ale možné, že ses počtem iterací přibližně trefil do délky sekvence generátoru pseudonáhodných čísel vestavěného v daných prohlížečích (~5 milionů). To pak ale není chyba algoritmu, jak je koneckonců vidět z mého testu a i z konstrukce algoritmu jako takového. Pokud bych měl použít tvá slova, tak „Toto by malo byť náhodné práve tak ako funkcia Math.random.

Properly implemented, the Fisher–Yates shuffle is unbiased, so that every permutation is equally likely.
~ http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

Rád bych podotknul, že ten algoritmus je tak prostý, že je prakticky nemožné jej nesprávně implementovat - viz. výše zmíněný pseudokód.
_es
Profil
Witiko:
Je nepravděpodobné, ale možné, že ses počtem iterací přibližně trefil do délky sekvence generátoru pseudonáhodných čísel vestavěného v daných prohlížečích (~5 milionů)
To sa mi nezdá, pri takom počte by odchýlky vyrušili, odchýlka nastáva aj pri inom počte prvkov poľa a inom počte opakovaní. K náhodnému zoradeniu, spravenému „prehadzovaním“ prvkov v poli, mám nedôveru.
Witiko
Profil
_es:
K náhodnému zoradeniu, spravenému ‚prehadzovaním‘ prvkov v poli, mám nedôveru.
S tím asi budeme muset žít, ten algoritmus totiž vypadá zcela legitimně:

0, 1, 2, 3, 4 - vezmu 4ku a vyměním jí s jedním z nevyznačených prvků vlevo (i = 4, j = 2)
0, 1, 4, 3, 2 - vezmu 3ku a vyměním ji s jedním z nevyznačených prvků vlevo (i = 3, j = 1)
0, 3, 4, 1, 2 - vezmu 4ku a vyměním ji s jedním z nevyznačených prvků vlevo (i = 2, j = 0)
4, 3, 0, 1, 2 - vezmu 3ku a vyměním ji s jedním z nevyznačených prvků vlevo (i = 1, j = 1)
4, 3, 0, 1, 2 <= Výsledek

Vyznačené náhodně posunuté pole, které se tvoří napravo od i je prokazatelně pseudonáhodné. Osobně tedy nevidím v algoritmu problém a zdá se mi nezaujatý. Jde pouze o instinkt, nebo tam vidíš nějakou skutečnou potíž?

To sa mi nezdá, pri takom počte by odchýlky vyrušili
Právě že pokud by ses trefil do délky pseudonáhodné sekvence, tak budeš dostávat pořád zcela stejné výsledky. Jinak ta čísla se mají 2000000 blížit, tzn. to, že se jim nerovnají, je zcela přirozené. Průměrná odchylka se bude zmenšovat s velikostí vzorku.
_es
Profil
Witiko:
Jinak ta čísla se mají 2000000 blížit, tzn. to, že se jim nerovnají, je zcela přirozené.
No nie je prirodzené, že sa pri opakovanom teste líšia o približne rovnakú hodnotu s rovnakým znamienkom, rádovo v percentách.

Jde pouze o instinkt, nebo tam vidíš nějakou skutečnou potíž?
Ako „potiaž“ sa mi vidí, že sa vymieňajú aj prvky, ktoré už boli vymenené, nezdá sa mi to.

Zdá sa mi, že ten algoritmus je nedokonalý, lebo ak tú tvoju metódu vykonám v tom teste dva krát za sebou, tak sa výsledky viac blížia priemeru. Len zvyšovanie počtu jedného zamiešania nestačí - odchýlka je stále významná. Akým spôsobom si robil test? Ak tak, že si stále miešal to isté pole, tak sa ti nedokonalosť algoritmu zmiernila - na test treba opakovane miešať pole s tými istými hodnotami na tých istých miestach.

this[i] = this[(j = Math.round(i-- * Math.random()))];
Nemala by byť namiesto metódy Math.round použitá metóda metóda Math.floor na o 1 vyššiu hodnotu?
Witiko
Profil
_es:
Bohužel tvé výsledky se mi jak na Firefoxu, tak v Chrome nepodařilo reprodukovat. Provedl jsem daný test i s tebou uvedenou funkcí s podobnými výsledky. Průměry navracených hodnot se vždy blížily k 2000000 a vždy podobnou rychlostí. Nemám tedy důvod nevěřit deklaraci z wikipedie, pokud nenajdeš v algoritmu nějaký problém, který by potvrzoval, že Tvé výsledky nejsou zkreslené nativním generátorem pseudonáhodných čísel.
_es
Profil
Witiko:
Akým spôsobom si tú tvoju metódu testoval?
Ja som použil presne tento kód:
<!doctype html>
<script>
Array.prototype.shuffle = function() { 
  var i = this.length - 1, j, temp;
  while(i) { 
    temp = this[i]; 
    this[i] = this[(j = Math.round(i-- * Math.random()))]; 
    this[j] = temp;
  } 
};
var n=1000000, s = new Array(n);
for(var i = 0; i < n; i++){s[i] = [0,1,2,3,4];s[i].shuffle();}
for(var i = 0, v = [0,0,0,0,0]; i < n; i++)for(var j = 0; j < 5; j++)v[j] += s[i][j];
document.write(v);
</script>
Witiko
Profil
_es:
var arr = [0,0,0,0,0], a; function res(){var poc = 5, p = [], x = []; 
for(var i = 0; i < poc; ++i) p[i] = i; 
for(i = 0; i < poc; ++i) x[i] = p.splice(Math.floor(Math.random() * (poc - i)), 1)[0]; 
return p = x;} var i = 0; while(i++ < 1000000) {
  a = res(); a.forEach(function(a,b) {arr[b] += a;});
} arr;
pro tu tvojí a
Array.prototype.shuffle = function() { 
  var i = this.length - 1, j, temp;
  while(i) { 
    temp = this[i]; 
    this[i] = this[(j = Math.round(i-- * Math.random()))]; 
    this[j] = temp;
  } 
};
var arr = [0,0,0,0,0], a = [0,1,2,3,4], i = 0; while(i++ < 1000000) {
  a.shuffle(); a.forEach(function(a,b) {arr[b] += a;});
} arr;
pro tu mojí.
_es
Profil
Witiko:
var arr = [0,0,0,0,0], a = [0,1,2,3,4], i = 0; while(i++ < 1000000) {
a.shuffle(); a.forEach(function(a,b) {arr[b] += a;});
} arr;
Ale ty miešaš stále to isté pole - teda to nie je korektný test - miešaš už zamiešané pole. Na korektný test musíš opakovane miešať pole s tými istými hodnotami na tých istých miestach.
Witiko
Profil
_es:
Zajímavé, skutečně to stále navrací číslice ve tvaru:
~19500000, ~19500000, ~20500000, ~20500000, ~20000000

Jsou tedy tři možnosti:
1) Problém se nachází ve funkci Math.random() - řešením je použít vlastní generátor s několika různými seedy
2) Špatně jsem algoritmus implementoval - stačí kontrola vůči pseudokódu
3) Wikipedia uvádí nefunkční algoritmus a nesprávné informace - nepravděpodobné
_es
Profil
Witiko:
Špatně jsem algoritmus implementoval - stačí kontrola vůči pseudokódu
Nejde o nevhodné použitie funkcie Math.round, spomenuté v [#19]?
Witiko
Profil
_es:
Viz. pseudokód - j random integer with 0 ≤ j ≤ i.
Tedy chci výsledek v intervalu <0; i> - tzn. j = Math.round(Math.random() * i)
_es
Profil
Witiko:
Tedy chci výsledek v intervalu <0; i> - tzn. j = Math.round(Math.random() * i)
No ale ide o to, s akou pravdepodobnosťou dostaneš výsledné celé číslo. Pre päť prvkov to bude interval <0; 4), po použití funkcie Math.round môžu byť výsledkom celé čísla v rozsahu 0 až 4, no 0 a 4 budú len s polovičnou pravdepodobnosťou voči zvyšným trom číslam - prislúcha im len polovičný interval, než ostatným číslam.
Witiko
Profil
_es:
Dobrý postřeh, mělo mě to napadnout.
Array.prototype.shuffle = function() {  
  var i = this.length, j, temp;  
  while(i) { 
    j = Math.floor(i-- * Math.random()); 
    temp = this[i];  
    this[i] = this[j];  
    this[j] = temp;  
  }  
};

Test navrací:
2001505, 2002627, 2000500, 1998941, 1996427
2000514, 2000690, 1998731, 2001456, 1998609
2001200, 1999862, 1999121, 1998798, 2001019
peta
Profil
Witiko, _es:
Zadani je takove, mam 10 fotek (vic pres js zobrazovat nebudu). Chci zobrazit z toho 6 nahodnych a chci, aby jich bylo co nejvice rozdilnych pri obnoveni stranky.
A ty cizi slova si klidne nechte pro matematickou fakultu, co jsem tak okem zahledl.

_es
"Nepotrebujem nič skúšať, matematika zo stredoškolského vzdelania mi stačí na to"
Evidentne ne.

Witiko
"že sem napíšu svou kosmologickou konstantu 0.66"
Pouze jsem napsal funkcni reseni, ktere pouzivam uz asi rok. Ty jsi to oznacil kosmoligickou konstantou a zacal offtopic diskuzi na tema Serazovaci algoritmy.
Coz jsem ovsem nezpochybnil je, ze s 0.5 je to dalsi mozne reseni.

_es, Witiko:
A porovname vysledky:
<script>
function mytest(arr,v,vysl)
{
for (var i=0; i<v; i++) {if (arr[i]>=1 && arr[i]<=v) {vysl[0]++; vysl[1]+=Math.abs((arr[i]-1)-i);}}; return vysl;
}

function myshow(name,vysl)
{
return "\n"+name+': ' + vysl[0] + ', ' + vysl[1] + ' a pomer je '+ Math.floor(vysl[1]/vysl[0]*1000)/1000;
}

var a,v,t,i,j;
t = '';
v = 6;

vysl = [0,0];
for (i=0;i<100;i++)
{
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
a = a.sort(function(){return 0.66 - Math.random();});
mytest(a,v,vysl);
}
t+= myshow('random 0.66',vysl);

vysl = [0,0];
for (i=0;i<100;i++)
{
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
a = a.sort(function(){return Math.random() - 0.5;});
mytest(a,v,vysl);
}
t+= myshow('random 0.5',vysl);


Array.prototype.shuffle = function() {
var i = this.length - 1, j, temp;
while(i) {
temp = this[i];
this[i] = this[(j = Math.round(i-- * Math.random()))];
this[j] = temp;
}
return this; //tady schazel return, ve FF mi to nejelo
}; 

vysl = [0,0];
for (i=0;i<100;i++)
{
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
a = a.shuffle();
mytest(a,v,vysl);
}
t+= myshow('shuffle',vysl);


alert(t+"\
\nPrvni cislo je pocet opakovani v intervalu 0-6 pozice, ktery by mel byt co nejmensi.\
\nDruhe cislo je soucet vzdalenosti od vychozi pozice, ktery by mel byt co nejvetsi, aby uzivatel nabyl dojmu, ze je to promichano lepe.\
");
</script>

Me to po nekolika refresh vychazi opakovane nejak takto:
random 0.66: 363, 677 a pomer je 1.865
random 0.5: 434, 677 a pomer je 1.559
shuffle: 351, 685 a pomer je 1.951

Proc to tak vychazi? Protoze algoritmus pro serazeni, ktery uziva javascript se nazyva netechnicky Sito a to tridi na hromadky s mensimi cisly a vetsimi cisly. Min a max cislo je testovano jen jedenkrat a tedy v pripade 50:50 u nej dojde k posunuti z mista pouze s pravdepodobnosti 50:50. Cili muze zustat na miste. A to jsem presne nechtel.

Uprava1: V algoritmu pro cislo 1 byla chyba, vzdy to zobrazovalo stejne 600, opraveno, chybny spojovac podminek :)
Uprava2: Pro zamichani vetsiho pole nahodne bych to resil predgenerovanim nekolika nahodnych hodnot, ktere bych pak vybiral pomoci hodnoty[i%pocethodnot], protoze math.random je pomala funkce.
Uprava3: Pridal jsem tam pomer obou hodnot, ktery vystihuje kvalitu promichani
_es
Profil
peta:
Proc to tak vychazi?
Ale ono to nevychádza:
Otestoval som rôzne spôsoby zamiešania 1 000 000 krát s percentuálnym štatistikou:
10.01, 10.00,  9.99, 10.00, 10.01, 10.00,  9.99, 10.00, 10.01, 10.00  Miešanie špeciálnym prehadzovaním prvkov v poli
10.00, 10.01, 10.00, 10.00,  9.99, 10.00, 10.00, 10.01,  9.99, 10.00  Miešanie náhodným vyraďovaním z poľa do iného poľa
 8.28,  8.29,  7.76,  7.32,  8.70,  8.71, 10.29, 10.71, 14.73, 15.21  Metóda sort s konšatntou 0.5
12.77, 12.26, 10.09,  8.45,  8.49,  7.83,  9.06,  8.09, 11.58, 11.38  Metóda sort s „Petovou“ konštantou 0.66

Testované vo Firefoxe 6.0.2, v iných prehliadačoch môžu byť posledné dva spôsoby výraznejšie odlišné.
Testovací skript:
<!doctype html>
<script>
function shuffle1(p) {  
  var i = p.length, j, temp;  
  while(i) { 
    j = Math.floor(i-- * Math.random()); 
    temp = p[i];  
    p[i] = p[j];  
    p[j] = temp;  
  }
  return p;  
}

function shuffle2(p) {  
  var x = [p.length], i = p.length;
  while(i) x[i - 1] = p.splice(Math.floor(Math.random() * i--), 1)[0];
  return x;
}

function shuffle3(p) {  
return p.sort(function(){return 0.5 - Math.random();});
}

function shuffle4(p) {  
return p.sort(function(){return 0.66 - Math.random();});
}

function test(f) {
  var n=1000000, s = new Array(n);
  for(var i = 0; i < n; i++)s[i] = f([0,1,2,3,4,5,6,7,8,9]);
  for(var i = 0, v = [0,0,0,0,0,0,0,0,0,0]; i < 10; i++) {
    for(var j = 0; j < n; j++) v[i] += s[j][i];
    v[i] /= 450000;
    v[i] = (Math.round(v[i]*100)/100).toFixed(2);
  }
  document.write(v + "<BR>");
}
test(shuffle1);
test(shuffle2);
test(shuffle3);
test(shuffle4);
</script>
« 1 2 »

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0