Like this?
A couple of iterations is enough to find the interval.
A small cost to create a few arrays when starting pays off in no time.
data VALUES;
do I=1 to 1000;
A=int(ranuni(0)*1000000); %* interval limits;
B=int(ranuni(0)*1000000); %* values to slot in;
output;
end;
run;
proc sql noprint;
select A into :VALUES separated by ' ' from VALUES order by A;
quit; %put &=values;
%macro floor(num,round); %* Floor() has just one parameter booo !;
round(&num,&round)-ifn(round(&num,&round)>&num, &round, 0)
%mend;
data WANT;
array V[1000] _temporary_ (&values.); %* array of values;
array V1_[1000] _temporary_ ; %* array of values rounded to 1e1;
array V2_[1000] _temporary_ ; %* array of values rounded to 1e2;
array V3_[1000] _temporary_ ; %* array of values rounded to 1e3;
array V4_[1000] _temporary_ ; %* array of values rounded to 1e4;
array V5_[1000] _temporary_ ; %* array of values rounded to 1e5;
if _N_=1 then do I=1 to 1000; %* populate rounded-value arrays ;
V1_[I] =%floor(V[I],1e1);
V2_[I] =%floor(V[I],1e2);
V3_[I] =%floor(V[I],1e3);
V4_[I] =%floor(V[I],1e4);
V5_[I] =%floor(V[I],1e5);
end;
set VALUES(keep=B); %* read data;
POS1e5 =whichn(%floor(B,1e5), of V5_[*]); %* find closest ;
if POS1e5 then POS1e4=whichn(%floor(B,1e4), of V4_[*]); %* but lower value;
if POS1e4 then POS1e3=whichn(%floor(B,1e3), of V3_[*]);
if POS1e3 then POS1e2=whichn(%floor(B,1e2), of V2_[*]);
if POS1e2 then POS1e1=whichn(%floor(B,1e1), of V1_[*]);
POS=max(1,of POS1e1-POS1e5);
%* Iterate array from POS (which() doesnot accept partial arrays booo !);
%* A couple of iterations at most is typically enough to find the interval;
do I=POS to 999;
if V[I] <= B <= V[I+1] then do;
ITER=I-POS;
output;
leave;
end;
end;
keep B I;
*keep POS1e: POS ITER V1-V3 ; %* debug;
run;
... View more