代码之家  ›  专栏  ›  技术社区  ›  roffensive

SAS中无重复随机数的生成

sas
  •  1
  • roffensive  · 技术社区  · 6 年前

    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 回复  |  直到 6 年前
        1
  •  1
  •   user667489    6 年前

    你相当接近一个工作,如果错综复杂的解决方案。出于教育目的,尽管data\u null\u的答案要简洁得多,但下面是代码不起作用的原因:

    • 您的leave语句位于另一个do循环中的do end块中。Leave语句只会跳出最内部的do循环,因此您的语句没有任何效果。
    • continue
    • 因为您正在用新发现的唯一值更新数组 之前 你增加了 counter ,以前填充的值将被覆盖。这通常会导致输出中出现重复的覆盖值。

    我会把 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;
    

    这是一个与所有 离开 持续 语句替换为可读性更强的替代语句:

    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;
    
        2
  •  3
  •   data _null_    6 年前

    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