Генерация случайных чисел без повторений в SAS - PullRequest
0 голосов
/ 16 сентября 2018

Я пытаюсь получить случайную генерацию чисел без повторения.Моя идея состоит в том, чтобы сделать цикл while, который пойдет 5 раз.Внутри я получу случайный номер, сохраню его в таблице и проверяю на каждой итерации, есть ли выбранный номер в таблице или нет, а затем решаю, является ли этот случайный выбор повторением или нет.

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

data WithoutRepetition;
counter = 0;
array temp (5)  _temporary_;
do while(1);
    rand=round(4*ranuni(0) +1,1);

    if counter = 0 then 
    do;
        temp(1) = rand;
        counter=counter+1;
        output;
        continue;
    end;    

    do a=1 to counter by 1;      
        if  temp(a) = rand then continue ;   
    end; 
        temp(counter) = rand;
        output;
        counter=counter+1;
        if counter = 5 then do; 
            leave;
        end;  
end;    
run;

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Вы были достаточно близки к рабочему, если извилистому решению.В образовательных целях, хотя ответ _null_ для данных намного чище, вот почему ваш код не работал:

  • Ваше заявление об отпуске находится внутри блока do-end, который находится внутри другого цикла do.Операторы Leave выходят только из внутреннего цикла do, так что ваши действия не действуют.
  • То же самое верно и для ваших операторов continue, первое из которых совершенно не нужно.
  • Потому чтовы обновляете свой массив новыми найденными уникальными значениями до , вы увеличиваете counter, ранее заполненные значения перезаписываются.Это часто приводит к дублированию перезаписанных значений, появляющихся в вашем выводе.

Я бы поместил continue и leave в ту же категорию, что и goto - избегайте их использования, если это возможно,поскольку они, как правило, затрудняют отладку кода.Более ясно установить условия выхода для всех ваших циклов в точке входа.

Просто для забавы, но вот фиксированная версия вашего исходного кода:

data WithoutRepetition;
  counter = 0;
  array temp (5)  _temporary_;
  do while(1);
    rand=round(4*ranuni(0) +1,1);

    if counter = 0 then do;
      temp(1) = rand;
      counter +1;
      output;
    end;

    dupe = 0;
    do a=1 to counter;
      if temp(a) = rand then dupe=1;
    end; 

    if dupe then continue;

    counter +1;
    temp(counter) = rand;
    output;
    if counter = 5 then leave;  
  end;    
run;

А вотэквивалентная версия со всеми операторами leave и continue, замененными более удобочитаемыми альтернативами:

data WithoutRepetition;
  counter = 0;
  array temp (5)  _temporary_;
  do while(counter < 5);
    rand=round(4*ranuni(0) +1,1);

    if counter = 0 then do;
      temp(1) = rand;
      counter +1;
      output;
    end;

    else do;
      dupe = 0;
      do a=1 to counter while(dupe = 0);
        if temp(a) = rand then dupe=1;
      end; 

      if dupe = 0 then do;
        counter +1;
        temp(counter) = rand;
        output;
      end;
    end;

  end;    
run;
0 голосов
/ 16 сентября 2018

Звучит так, как будто вы хотите случайную перестановку.

165  data _null_;
166     seed=12345;
167     array r[5] (1:5);
168     put r[*];
169     call ranperm(seed,of r[*]);
170     put r[*];
171     run;

1 2 3 4 5
5 1 4 3 2

Это упрощенная версия того, что вы пытаетесь сделать.

data WithoutRepetition;
   i=0;
   array temp[5];
   do r=1 by 1 until(i eq dim(temp));
      rand=round(4*ranuni(0)+1,1);
      if rand not in temp then do; i+1; temp[i]=rand; end;
      end;
   drop i rand;
   run;

enter image description here

...