Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   rand в php два рендома друг с другом связаны (https://javascript.ru/forum/server/8335-rand-v-php-dva-rendoma-drug-s-drugom-svyazany.html)

Jekel 20.03.2010 00:19

rand в php два рендома друг с другом связаны
 
Как сделать так, чтобы $rnd2 не учитывало $rnd? Тоесть чтобы $rnd никогда не было равно $rnd2.:blink:
$kol = mysql_num_rows(mysql_query("SELECT * FROM writers"));

$rnd = rand(1, $kol);

$db1 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rnd."'"));

$rnd2 = rand(1, $kol);

$db2 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rnd2."'"));

Gvozd 20.03.2010 00:33

да тысяча способов.
while( ($rnd2 = rand(1, $kol)) ==$rnd);

subzey 20.03.2010 00:53

Гхм… Если Вам нужно две различные случайные строки из таблицы, то так и составляйте запрос:
Код:

SELECT * FROM `writers` ORDER BY RAND() LIMIT 2
UPD: Надеюсь, столбец id хотя бы уникальный?

Gvozd 20.03.2010 01:23

subzey,
вы в своем уме?
сложность вычислений при таком запросе O(N*lg(N))
и все это ради двух строчек.
В то время, как способ Jekel делает это за O(lg(N))
Разницу чуствуете?
PS Вспомнилось

subzey 20.03.2010 01:45

Gvozd,
вроде, пока да. На стенде, может, это и работает лучше, но как насчет практики?

Авторы никогда не будут удаляться? id всегда-всегда будут идти строго по порядку, а обоспечивать это будут триггеры, или «ручка слива»?

А что, если запись будет всего одна?
while( ($rnd2 = rand(1, 1)) ==$rnd);

Jekel 20.03.2010 02:15

спасибо, while (($rnd2=rand(1, $db1n))==$rnd){} работает)

Gvozd 20.03.2010 06:42

Цитата:

Сообщение от subzey
Авторы никогда не будут удаляться? id всегда-всегда будут идти строго по порядку, а обоспечивать это будут триггеры, или «ручка слива»?

это просто набор исключительных случаев, которые надо описать в логике PHP-скрипта, в пользу производительности.
Цитата:

Сообщение от subzey
На стенде, может, это и работает лучше, но как насчет практики?

и на практике это решение остается более производительным, чем ваш очень удобный один запрос.
если хотите я могу протестировать насколько именно и опубликовать результаты

B@rmaley.e><e 20.03.2010 09:06

А зачем три запроса к одной траблице, когда в результате первого запроса уже все есть?

$res = mysql_query("SELECT * FROM writers"); // как ни крути, тяжеллый запрос
$res_length = mysql_num_rows($res);
$entries = array();
$i = 1;
$rnd1 = rand(1, $res_length);
while( ($rnd2 = rand(1, $res_length)) == $rnd1);

while($row = mysql_fetch_assoc($res)){
   if($i == $rnd1) $entries[0] = $row;
   if($i == $rnd2) $entries[1] = $row;
   $i++;
   if(count($entries) == 2) break;
}

subzey 20.03.2010 11:14

Цитата:

Сообщение от Gvozd
надо описать в логике PHP-скрипта, в пользу производительности.

Вот… это меня и смущает; по-моему, это задача для уровня БД, а не приложения. (Но, возможно, меня просто развратил PostgreSQL).

B@rmaley.e><e,
купить торт и съесть только вишенку. Тоже вариант, только, наверное, вместо while по mysql_fetch_assoc() — mysql_data_seek().

Gvozd 21.03.2010 00:40

Цитата:

Сообщение от subzey
это задача для уровня БД

по логике-да
к сожалению, все известные мне решения на чистом MySQL весьма и весьма непродуктивны.
например ваше решение, как раз и есть то, за что вы осуждаете других
Цитата:

Сообщение от subzey
купить торт и съесть только вишенку

вычислить для каждой строки таблицы случайную величину, отсортировать эту кучу случайных чисел а затем взять только строку, или две.

subzey 22.03.2010 13:40

Gvozd,
да я и не спорю про эффективность. Что может быть шустрее, чем выборка двух значений по полю-индексу? (Более того, поколдовал я и так и сяк, и с JOIN и с "LIMIT {random}, 1", при нескольких тысячах строк результаты ужасают.)

Просто тогда надо быть очень внимательным и держать id в чистоте и порядке.

Да, и багрепорт, видимо, проигнорировали.

// допустим, $kol = 1;
$rnd = rand(1, $kol); // 1, всегда
while( ($rnd2 = rand(1, $kol)) ==$rnd); // бесконечный цикл

Gvozd 22.03.2010 15:51

Цитата:

Сообщение от subzey
Да, и багрепорт, видимо, проигнорировали.

Цитата:

Сообщение от Gvozd
это просто набор исключительных случаев, которые надо описать в логике PHP-скрипта, в пользу производительности.

достаточно несложно организовать ф-цию, которая это учтет.
так что это скорее вопрос уже формализации
Цитата:

Сообщение от subzey
Просто тогда надо быть очень внимательным и держать id в чистоте и порядке.

можно сделать проще:
$rnd = rand(1, $kol);

$db1 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers ORDER BY id LIMIT ".$rnd.",1"));

если я правильно предполагаю, то такой запрос должен отрабатыватся за логарифм, также как и получение по id

subzey 22.03.2010 20:22

Сообщение не дошло (долбаный MTS!).

Лениво переписывать тираду, да и не вспомню уже, вкратце, проверил на живом сервере, а не дома на денвере, и метод с LIMIT оказался действительно неплох (0,02 с для 36000 строк).

Вот, только с ORDER BY он работает на порядок медленнее, действительно ли он нужен, учитывая, что порядок строк нам не особо-то и нужен.

Gvozd 22.03.2010 21:15

Цитата:

Сообщение от subzey
действительно ли он нужен

да нафих не сдался, если уж на то пошло.
Цитата:

Сообщение от subzey
работает на порядок медленнее

а поле проиндексировано?

Jekel 25.03.2010 14:48

Теперь нужно три картинки выводить...три юзера. Как в этом случае сделать? так while ((($rnd3=rand(1, $db1n))==$rnd)==$rnd2); не работает(
<?php

mysql_connect($hostddd, $userdbddd, $passdbddd); 
mysql_select_db($databaseddd);

$db1n = mysql_num_rows(mysql_query("SELECT * FROM writers"));

$rnd = rand(1, $db1n);

$db1 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rnd."'"));

$wri = "<a href='index.php?option=com_content&view=article&id=48#".$db1['id']."'>
<img src='http://localhost/writers/".$db1['photo']."'></img></a>
<br>
<b>".$db1['name']."</b><br><span style='font-size: 11px'>Age: ".$db1['age']."</span>
<br><span style='font-size: 11px'>Country of Residence: ".$db1['country']."</span>
<br><span style='font-size: 11px'>Degree: ".$db1['degree']."</span><br><br>";

while (($rnd2=rand(1, $db1n))==$rnd);

$db2 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rnd2."'"));

$wri2 = "<a href='index.php?option=com_content&view=article&id=48#".$db2['id']."'>
<img src='http://localhost/writers/".$db2['photo']."'></img></a>
<br>
<b>".$db2['name']."</b><br><span style='font-size: 11px'>Age: ".$db2['age']."</span>
<br><span style='font-size: 11px'>Country of Residence: ".$db2['country']."</span>
<br><span style='font-size: 11px'>Degree: ".$db2['degree']."</span><br><br>";

echo "<br>".$wri.$wri2;
?>

Gvozd 25.03.2010 15:50

$max=100;
$count=10;


$rand=array();$temp_rand=NULL;
for($i=0;$i<$count;$i++)
    {
    while(in_array($temp_rand=rand(1,$max),$rand));
    $rand[$i]=$temp_rand;
    }

Kolyaj 25.03.2010 16:03

$max=100;
$count=10;
$rand = array();
for ($i = 0; $i < $count; $i++) {
    $rand[$i] = rand(1, $max - $i);
    for ($j = 0; $j < $i; $j++) {
        if ($rand[$i] >= $rand[$j]) {
            $rand[$i]++;
        }
    }
}

$count равномерно распределённых случайных чисел.

Gvozd 25.03.2010 16:14

Kolyaj,
обоснуй
не очень-то похоже, что это будет равномерная выборка
более того, она и вправду неравномерная
для выборки 3х элементов из 4х, оно дает:
7 перестановок "123"
5 перестановок "124"

Jekel 25.03.2010 16:27

Не могу вьехать как его влепить туда....пожалуйста, можно на моем примере?

Gvozd 25.03.2010 16:53

Цитата:

Сообщение от Jekel
Не могу вьехать как его влепить туда

я дико извиняюсь, но это совсем элементарщина
код, не такой уж сложный, и полагаю без комментариев должно быть ясно что он делает, и как использовать его результат

e1f 25.03.2010 18:37

Kolyaj, емнип, равномерно будет как-то так:
$max = 100;
$count = 10;
$rand = array();
for ($i = $max; $i--; ) {
    array_push($rand, 1+$i);
}

for ($i = $max; --$i; ) {
    $j = rand(0, $i);
    list($rand[$i], $rand[$j]) = array($rand[$j], $rand[$i]);
}

$rand = array_slice($rand, 0, $count);

Gvozd 25.03.2010 22:34

блин, жаль тут нету смайлика бьющегося головой об стену.
e1f,
это у тебя такая сильно хитро выделанная замена shuffle?
зачем изобретаешь велосипед?
почему бы вообще тогда не воспользоваться array_rand?
$max=100;
$count=10;

$rand=array();
for($i=1;$i<=$max;$i++)
    $rand[$i]=$i;
$rand=array_rand ($rand,$count);

но работает, оно медленнее(при больших $max и малых $count) чем мое решение

Jekel 25.03.2010 23:52

Warning: in_array() [function.in-array]: Wrong datatype for second argument in /tmp/htmlRZcyZm on line 21

21:
while(in_array($temp_rand=rand(1,$max),$rand_array ));

Gvozd 26.03.2010 00:01

исправил
как вы работаете на PHP, если не в состоянии определить и исправить опечатку в 6-и строках кода?

Jekel 26.03.2010 00:10

Вы никогда не учились?

Все прекрастно работает, спасибо большое
<?php

mysql_connect($hostddd, $userdbddd, $passdbddd); 
mysql_select_db($databaseddd);

$db1n = mysql_num_rows(mysql_query("SELECT * FROM writers"));

///////////////////////////////////////////

$rand=array();$temp_rand=NULL; 
for($i=0;$i<$db1n;$i++) 
    { 
    while(in_array($temp_rand=rand(1,$db1n),$rand)); 
    $rand[$i]=$temp_rand; 
    }

/////////////////////////////////////////////

$db1 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rand[0]."'"));

$wri = "<a href='index.php?option=com_content&view=article&id=48#".$db1['id']."'>
<img src='http://localhost/writers/".$db1['photo']."'></img></a>
<br>
<b>".$db1['name']."</b><br><span style='font-size: 11px'>Age: ".$db1['age']."</span>
<br><span style='font-size: 11px'>Country of Residence: ".$db1['country']."</span>
<br><span style='font-size: 11px'>Degree: ".$db1['degree']."</span><br><br>";

$db2 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rand[1]."'"));

$wri2 = "<a href='index.php?option=com_content&view=article&id=48#".$db2['id']."'>
<img src='http://localhost/writers/".$db2['photo']."'></img></a>
<br>
<b>".$db2['name']."</b><br><span style='font-size: 11px'>Age: ".$db2['age']."</span>
<br><span style='font-size: 11px'>Country of Residence: ".$db2['country']."</span>
<br><span style='font-size: 11px'>Degree: ".$db2['degree']."</span><br><br>";

$db3 = mysql_fetch_assoc(mysql_query("SELECT * FROM writers WHERE id='".$rand[2]."'"));

$wri3 = "<a href='index.php?option=com_content&view=article&id=48#".$db3['id']."'>
<img src='http://localhost/writers/".$db3['photo']."'></img></a>
<br>
<b>".$db3['name']."</b><br><span style='font-size: 11px'>Age: ".$db3['age']."</span>
<br><span style='font-size: 11px'>Country of Residence: ".$db3['country']."</span>
<br><span style='font-size: 11px'>Degree: ".$db3['degree']."</span><br><br>";

echo "<br>".$wri.$wri2.$wri3;
?>

Gvozd 26.03.2010 00:59

Цитата:

Сообщение от Jekel
Вы никогда не учились?

извините, если слишком предубежденно к вам отнесся.
да, я когда-то учился.
начинал я достаточно медленно и спокойным равномерным темпом.
к моменту, когда я начал изучать БД, и работу PHP с ними, я был уже в состоянии использовать/отладить такой кусок кода.
хотя ваш вопрос, у меня вполне мог возникнуть, из-за незнания многих ф-ций PHP, и качественного алгоритмического мышления

e1f 26.03.2010 02:42

Gvozd,
чооорт, у моего велосипеда ОЧЕНЬ круглые колеса :)
мда, действительно, если приходить в PHP из Perl, то есть велосипеды :)

Gvozd 26.03.2010 03:54

Цитата:

Сообщение от e1f
чооорт, у моего велосипеда ОЧЕНЬ круглые колеса

аналогию не понял
Цитата:

Сообщение от e1f
мда, действительно, если приходить в PHP из Perl, то есть велосипеды

ни за что не поверю что там нету аналогичных функций, и поэтому подобные операции приходится делать руками

e1f 26.03.2010 12:28

Gvozd, Вы не поверите ;)
Аналога array_shuffle в Перле нет. Можно использовать модуль List::Util, если очень хочется -- тогда будет. И да, там все сделано руками :)

Gvozd 26.03.2010 17:39

Цитата:

Сообщение от e1f
Вы не поверите
Аналога array_shuffle в Перле нет.

что-то у меня жесткое дежавю щаз)))
как же страшно, таки жить....

e1f 26.03.2010 18:07

Чорт, Вы это сказали, и у меня тоже возникло :)
Да, есть немного :)
http://javascript.ru/forum/server/65...tirovka-2.html

Gvozd 26.03.2010 18:12

именно))))
значит моя память еще меня не подводит))


Часовой пояс GMT +3, время: 04:07.