Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > rand()


Автор: ДобренькийПапаша 29.4.2006, 19:38
Итак, как сделать так, чтобы рандились, либо -1, либо -2, либо 1, либо 2. Функция вызывается рекурсивно, надо, чтобы постоянно рандилось в разной последовательности. 

Автор: BreakPointMAN 29.4.2006, 19:56
В чем проблема? 

Автор: ДобренькийПапаша 29.4.2006, 20:06
Надо запрограммировать смещение коня в шахматах. Для этого мне надо чтобы рандились эти четыре числа.  

Автор: BreakPointMAN 29.4.2006, 20:19
ну и? что не получается-то? как функция rand() работает, ты знаешь? 

Автор: Kuber 29.4.2006, 20:24
Цитата(ДобренькийПапаша @ 29.4.2006,  19:38)
Итак, как сделать так, чтобы рандились, либо -1, либо -2, либо 1, либо 2. Функция вызывается рекурсивно, надо, чтобы постоянно рандилось в разной последовательности.

Код

switch(rand()%3)
        {
        case 0:
            Tmp=-1;
            break;
        case 1:
            Tmp=-2;
            break;
        case 2:
            Tmp=1;
            break;
        case 3:
            Tmp=2;
            break;
        }


Попробуй так... 

Автор: BreakPointMAN 29.4.2006, 20:30
Kuber, Бог ты мой! А еще подлиннее нельзя было?!??!?!?  smile  smile  

Автор: ДобренькийПапаша 29.4.2006, 20:40
Рандит только 0. Прога конечно в разработке)))). Тут много неправильно пока что.

Код

#include <iostream.h>
#include <math.h>
#include <stdlib.h>

void knight(int i, int j, int n, bool a[8][8])
{
    
    for(;;)
    {
        switch(rand()%3)
        {
            
        case 0:
            n=-1;
            break;
        case 1:
            n=-2;
            break;
        case 2:
            n=1;
            break;
        case 3:
            n=2;
            break;
        }
        n=rand()%3;
        if(n=1) i++;
        if(n=1) j+2; 
        if(n=1) a[i+1][j+2]=false;
        if(n=1 && a[i+1][j+2]) knight(i,j,n,a); 
        cout<<n<<endl;
        if(n=2) i+2;
        if(n=2) j++;
        if(n=2) a[i+2][j+1]=false;
        if(n=2 && a[i+2][j+1]) knight(i,j,n,a);
        cout<<n<<endl;
    }
    

}
void main()
{
    int i=0, j=0, n;
    bool a[8][8];
    knight(i,j,n,a);
}
 

Автор: BreakPointMAN 29.4.2006, 20:55
Код

n=(n=rand()%4)>1?n-1:n-2;

Вот и всё.

Код

        case 3:
            n=2;
            break;
        }
        n=rand()%3; // затираешь новым значением нужное значение n
        if(n=1) i++;
 

Автор: Step 29.4.2006, 21:00
Цитата

Бог ты мой! А еще подлиннее нельзя было?!??!?!?       

если вы в таком тоне притендуете на краткость и оптимальность своего кода
Код

n=(n=rand()%4)>1?n-1:n-2;

то вынужден вас расстроить это не самое идеально решение


ЗЫ: это что бы вам предупреждения не влиплять 

Автор: BreakPointMAN 29.4.2006, 21:08
Цитата(Step @  29.4.2006,  21:00 Найти цитируемый пост)
то вынужден вас расстроить это не самое идеально решение

Ну, я не утверждал, что мое решение "самое идеально"...  smile Если вы знаете решение более "идеально", просветите нас, неразумных!  smile  Всегда приятно посмотреть на более красивый и короткий код, чем написанный собой. 

Автор: BreakPointMAN 29.4.2006, 21:49
Можно так еще... равновероятность повыше будет:
Код

n=(n=(rand() /((RAND_MAX+1)/4) ))-1-1*(n<=1);
  

Автор: Void 29.4.2006, 22:35
BreakPointMAN, во-первых, UB smile Двойное изменение n между точками следования.
Во-вторых, для въезжания в этот код требуется (ну по крайней мере мне) секунд 10–15. Write-only, одним словом. Хотя, если сопроводить комментарием…

Я бы, пожалуй, написал так, не претендуя ни на краткость, ни на производительность, но, надеюсь, на очевидность производимых действий:
Код
int n;
{
    static const int cases[] = {-2, -1, 1, 2};
    n = cases[4 * rand() / (RAND_MAX + 1)];
}
 

Автор: BreakPointMAN 29.4.2006, 23:00
Цитата(Void @  29.4.2006,  22:35 Найти цитируемый пост)
Двойное изменение n между точками следования.

Не-а...  smile или, быть может, я не вижу... Где?

В остальном согласен. 

Автор: Void 29.4.2006, 23:02
Код
(n=(rand() /((RAND_MAX+1)/4) ))

Раз assignment.
Код
n=(/***/)-1-1*(n<=1);

Два assignment.

Ы? smile 

Автор: nikitao 29.4.2006, 23:09
Господа,вы в своих спорах завязли,а человек ответа на свою проблему не получил smile 
Вообще полностью согласен с Void.С++сты часто с убийственным рвением укарачивают,сжымают код(благо язык очень гибкий),но про читабельность просто забывают. smile 
Ладно теперь по делу:
ДобренькийПапаша, у тебя всегда генерируется ноль из-за того что ты забыл про вызов srand()  smile

Добавлено @ 23:15 
А вот теперь,давайте пофлудим  smile 
Конструкции типа
Код

n=(n=(rand() /((RAND_MAX+1)/4) ))-1-1*(n<=1);

уже нехороши хатя бы тем,что два опытных программиста начинают спорить про их работаспасобность.Сегодня пусть эта конструкция работает,а завтра в попых чуть-чуть измененная уже не будет.Т е мы стоим на грани(если не перешли) практически безпречинно.Я не говорю ,что код надо упрощать до предела,просто во всем еадо знать меру. smile  

Автор: BreakPointMAN 29.4.2006, 23:16
ммм... наверное, прав... пошел я читать Стандарт и http://alenacpp.blogspot.com/2005/11/sequence-points.html.. smile 

Автор: Kuber 29.4.2006, 23:17
Думаю это не совсем к теме.smile
Люблю С++ за то(еще много за чтоsmile) что одно решение можно представить различными способами коих множество. Наверное многие тоже такого мнения. 

Автор: Fin 29.4.2006, 23:24
nikitao, srand нужен только для того, чтобы сбить генератор псевдослучайных чисел. Он никак не решает проблему 0.

Добавлено @ 23:29 
А что мне действительно нравится, так эта конструкция
Код

        if(n=1) i++;
        if(n=1) j+2; 
        if(n=1) a[i+1][j+2]=false;
        if(n=1 && a[i+1][j+2]) knight(i,j,n,a); 
        cout<<n<<endl;
        if(n=2) i+2;
        if(n=2) j++;
        if(n=2) a[i+2][j+1]=false;
        if(n=2 && a[i+2][j+1]) knight(i,j,n,a);
        cout<<n<<endl;
  

Автор: nikitao 29.4.2006, 23:29
Fin, или я тебя не понял или ты говоришь не правду:
Код

#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
    int x=rand();
    cout<<x;
    getch();
}

У меня всегда при запуске выдаёт 41,а у тебя будет выдовать другое,но постоянное число smile  

Автор: Fin 29.4.2006, 23:37
nikitao, Вот именно. Что постоянное число.  Произведи свой эксперемент дальше. И увидеш, что числа будут меняться. 
Код

#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
    int x;
    for(int i=0; i<4; i++)
    {
          x=rand();
          cout<<x << endl;
    }
    getch();
}


Чтобы этого не происходило при каждом запуске программы, ставят в самом начале вызов функции srand.  

Автор: nikitao 29.4.2006, 23:45
 smile А это в этом смысле. smile  

Автор: Fin 29.4.2006, 23:53
Та конструкция из кода, что я привел. Вот она решает проблему. Правда на распечатке должно быть сначало 1, а затем 2. Если учесть, что функция knight(i,j,n,a); никак не влияет на переменную n. 

Автор: Helicopterr 1.5.2006, 00:48
Цитата(Fin)
srand нужен только для того, чтобы сбить генератор псевдослучайных чисел. Он никак не решает проблему 0

  srand() (start rand) инициализирует rand, что необходимо для его работы.  

Код

srand(time(0)); //нужно записать в начале ф-ции
   

Автор: papam 1.5.2006, 14:42
Добренький папаша могу скинуть готовую прогу!Напиши куда!Тыж мне помогал!!!!!!!!!!!!!!!!!!!!! 

Автор: Heremum 1.5.2006, 18:53
Вы чего тут так извратились? Алгоритм простейший: генерируем с помощью rand() числа от -2 до 2:
Код

...
while(1)
{
    somevalue = rand()%4 - 4;
    if (somevalue == 0)
        somevalue = rand()%4 - 4;
    else
        break;
}
...
 

Автор: Helicopterr 1.5.2006, 23:50
Heremum
а ты результат своего кода видел?
у меня это:
-3, -2, -1, -3, -4, -2, -2, -2, -4
А теперь прочти условие задачи...
+ еще маленькая проблемка эта последовательность (у тебя на компе может быть другой) будет такой же при новом запуске программы. 
Вот мы тут и... как ты там написал? извращаемся?

 

Автор: AISIN 4.5.2006, 15:03
Цитата(Heremum @  1.5.2006,  18:53 Найти цитируемый пост)
код C++
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:


...
while(1)
{
    somevalue = rand()%4 - 4;
    if (somevalue == 0)
        somevalue = rand()%4 - 4;
    else
        break;
}


Цитата(Helicopterr @  1.5.2006,  23:50 Найти цитируемый пост)
-3, -2, -1, -3, -4, -2, -2, -2, -4

просто нужно     somevalue = rand()%4 - 4; 
исправить на somevalue = rand()%3 -rand()%3
 if (somevalue == 0)
somevalue = rand()%3 -rand()%3
Cразу скажу результата, не видел но должно работать
    

Автор: Heremum 4.5.2006, 17:52
Код

#include <stdio.h>
#include <stdlib.h>

void main()
{
    int somevalue = rand()%2 - 2;
    for (int i = 0; i < 5000; i++)
    {
        somevalue = rand()%2 - 2;
        if (somevalue == 0)
            somevalue = rand()%2 - 2;
    }
}

Значения в диапозоне [-2; 2].  

Автор: Fin 4.5.2006, 22:51
Heremum, Я надеюсь, ты условия задачи читал более внимательно, чем все остальные.
Цитата

Итак, как сделать так, чтобы рандились, либо -1, либо -2, либо 1, либо 2.

В данном коде 
Код

        somevalue = rand()%2 - 2;
        if (somevalue == 0)
            somevalue = rand()%2 - 2;

somevalue всегда будет или -1 или -2. Ты никогда не получиш значения 1 или 2. Так что твое высказывание 
Цитата

Вы чего тут так извратились? 

не совсем понятно.

По моему личному мнению, наиболее простой и надежный вариант предложил Void Только его нужно чуть доработать.
Код

int n;
{
    static const int cases[] = {-2, -1, 1, 2};
    n = cases[rand()%4];
}
 

Автор: Void 4.5.2006, 22:59
Fin, я не случайно написал так, как написал, а не rand() % 4. Это дает более равномерное распределение в случае ГПСЧ. 

Автор: Fin 4.5.2006, 23:04
Void, В твоем случае, могут быть проблемы с откидыванием дробной части. Так как Все числа целочисленые.

Добавлено @ 23:12 
Сейчас проверил у себя на компиляторе. Два подхода работают. Так что может быть я слишком перестраховываюсь smile . 

Автор: Void 4.5.2006, 23:12
Fin, если RAND_MAX достаточно велик (хотя бы 255), проблем не будет. 

Автор: Fin 4.5.2006, 23:22
RAND_MAX стандартно равен 32767

А вот код генератора псевдослучайных чисел, который стандартно поставляется вместе с библиотеками С
Код

#define RAND_MAX 32767

unsigned long next=1;

int rand(void) {
 next=next*1103515245+12345;
 return((unsigned int)(next/65536)%32768);
}

void srand(unsigned int seed) {
 next=seed;
}

Источник: http://algolist.manual.ru/maths/generator/standard.php 

Автор: Void 4.5.2006, 23:31
Цитата(Fin @  5.5.2006,  01:22 Найти цитируемый пост)
RAND_MAX стандартно равен 32767

Не совсем. В C99 сказано, что RAND_MAX должен быть не менее 32767. Что, впрочем, ситуации не меняет, спасибо за напоминание smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)