/**********************************************************************/
/* Example 1 */
data _null_;
x=0;
do i=1 to 10;
x+0.1;
put x=hex16. '(hex)' x='(formatted dec)';
end;
if x=1 then put 'x is equal to 1';
else put 'what happened?';
run;
/**********************************************************************/
/* Example 2 */
data _null_;
base=16; /* 16 for IBM, 2 for VAX and IEEE */
max_digt=14; /* 14 for IBM, 56 for VAX, 53 for IEEE */
/* Compute maximum integer and display */
max_int=base ** max_digt;
put @2 max_int= hex16. '(hex)' max_int comma22. '(dec)';
/* This DO loop attempts to store the five */
/* integers before and after the maximum. Notice */
/* that some of the integers after the maximum */
/* cannot be stored exactly. */
put / @2 'I' @8 'MAX_INT+I (in hex)' @31 'MAX_INT+I
(in dec)'
/ @1 '---' @8 '---------------' @31 '---------------';
do i=-5 to 5;
x=max_int+i;
put @1 i 2. @10 x hex16. @30 x comma22.;
end;
run;
/**********************************************************************/
/* Example 3 */
data _null_;
/* The first expression does not result in a value */
/* of zero. */
x= -16-0.1+16+0.1;
put x= hex16. x= '<= expression 1'/;
/* By breaking apart the expression, you can see */
/* where representation error is introduced and */
/* where loss of significance occurs. */
x= -16;
put x= hex16. x=;
x= x-0.1;
put x= hex16. x= '<= representation error';
x= x+16;
put x= hex16. x= '<= loss of significance';
x= x+0.1;
put x= hex16. x= /;
/* If you change the order of the operands, the */
/* expression will evaluate correctly. */
x= 16-16+0.1-0.1;
put x= hex16. x= '<= expression 2';
run;
/**********************************************************************/
/* Example 4 */
data _null_;
/* IBM systems */
x=255.115;
x_rnd=round(x,.01);
y=256.115;
y_rnd=round(y,.01);
put @10 'IBM systems' / _all_ / ;
/* VAX systems */
x=4095.175;
x_rnd=round(x,.01);
y=4096.175;
y_rnd=round(y,.01);
put @10 'VAX systems' / _all_ / ;
/* IEEE systems */
x=255.155;
x_rnd=round(x,.01);
y=256.155;
y_rnd=round(y,.01);
put @10 'IEEE systems' / _all_ / ;
run;
/**********************************************************************/
/* Example 5 */
%macro eqfuzz(var1, var2, fuzz=1e-12);
abs((&var1 - &var2) / &var1) < &fuzz
%mend;
data _null_;
x=0;
y=1;
do i=1 to 10;
x+0.1;
end;
if x=y then put 'x exactly equal to y';
else if %eqfuzz(x,y) then put 'x close to y';
else put 'x nowhere close to y';
run;
/**********************************************************************/
/* Example 6 */
%macro round(var,unit,base=16,fz_digit=12);
/* Macro parameters are as follows: */
/* var: variable to be rounded */
/* unit: round-off unit */
/* base: base used for numeric representation */
/* on the platform being used */
/* (base 16 for IBM, base 2 for VAX */
/* and IEEE) */
/* fz_digit: digit in representation where */
/* fuzz occurs */
/* (for IBM: maximum value is 14 */
/* suggested value is 12 */
/* for VAX: maximum value is 56 */
/* suggested value is 50 */
/* for IEEE: maximum value is 53 */
/* suggested value is 48). */
/* Note: Suggested value is less than */
/* maximum to allow for some loss of */
/* significance error as well as */
/* representation error. */
/* */
/* Fuzz factor is computed as follows: */
/* The log in the base of the representation */
/* is determined by taking the natural log of */
/* the value and dividing it by the natural */
/* log of the base. The resulting value is */
/* raised to the next integer to determine the */
/* magnitude of the value. The fz_digit */
/* parameter is subtracted from the magnitude */
/* of the value to determine the magnitude of */
/* the fuzz factor. The base is then raised to */
/* this magnitude and multiplied by the sign */
/* of the value to create the actual fuzz */
/* factor. This fuzz factor is added to the */
/* variable value, and the ROUND function */
/* is called. */
round((&var+
(sign(&var)*
&base**(ceil(log(abs(&var))/log(&base))-&fz_digit))),
&unit)
%mend round;
/**********************************************************************/
/* Example 7 */
data _null_;
/* IBM systems */
x=255.115;
x_rnd=%round(x,.01);
y=256.115;
y_rnd=%round(y,.01);
put @10 'IBM systems' / _all_ / ;
/* VAX systems */
x=4095.175;
x_rnd=%round(x,.01);
y=4096.175;
y_rnd=%round(y,.01);
put @10 'VAX systems' / _all_ / ;
/* IEEE systems */
x=255.155;
x_rnd=%round(x,.01);
y=256.155;
y_rnd=%round(y,.01);
put @10 'IEEE systems' / _all_ / ;
run;
/**********************************************************************/
/* Example 8 */
%macro eqfuzz(var1,var2,fuzz=1e-3);
abs(&var1-&var2)<=&fuzz
%mend;
data a;
input byval a_val $ a_group $;
cards;
1.0001 A1.0001 A-1-1
1.9999 A1.9999 A-2-1
4.0000 A4.0000 A-4-1
4.9999 A4.9999 A-5-1
5.0000 A5.0000 A-5-2
5.9999 A5.9999 A-6-1
6.0001 A6.0001 A-6-2
7.0000 A7.0000 A-7-1
7.0001 A7.0001 A-7-2
7.0001 A7.0001 A-7-3
;
data b;
input byval b_val $ b_group $;
cards;
2.0001 B2.0001 B-2-1
3.0000 B3.0000 B-3-1
3.9999 B3.9999 B-4-1
4.0001 B4.0001 B-4-2
4.0001 B4.0001 B-4-3
5.0000 B5.0000 B-5-1
5.0001 B5.0001 B-5-2
6.0000 B6.0000 B-6-1
8.0000 B8.0000 B-8-1
;
run;
data c;
length a_val b_val a_group b_group $ 8;
/* Get next BY value from each data set. */
retain a_count b_count 1;
if a_count<=a_nobs then
set a(keep=byval rename=(byval=next_a))
point=a_count nobs=a_nobs;
if b_count<= b_nobs then
set b(keep=byval rename=(byval=next_b))
point=b_count nobs=b_nobs;
/* Determine which data set needs to be advanced to */
/* merge current BY group. */
if %eqfuzz(next_a,next_b) then
do;
read_a=1;
read_b=1;
end;
else if next_a < next_b then
do;
read_a=1;
read_b=0;
end;
else do;
read_a = 0;
read_b = 1;
end;
/* If the end of one of the data sets has been */
/* reached, then get the remaining observations */
/* from the other data set. */
if a_count>a_nobs then
do;
read_a=0;
read_b=1;
end;
if b_count > b_nobs then
do;
read_a=1;
read_b=0;
end;
/* Check for beginning of a new BY group. */
if (read_a and not (%eqfuzz(next_a,byval))) or
(read_b and not (%eqfuzz(next_b,byval))) then
do;
/* Reset variables to missing. */
a_val=' ';
b_val=' ';
a_group=' ';
b_group=' ';
end;
/* Advance data set and write merged observation. */
if read_a then
do;
set a;
a_count+1;
end;
if read_b then
do;
set b;
b_count+1;
end;
drop next_a next_b read_a read_b;
run;
data a2;
set a;
byval=round(byval);
data b2;
set b;
byval=round(byval);
data c2;
merge a2 b2;
by byval;
run;
proc sql;
create table d as
select a.byval, a_val, b_val, a_group, b_group
from a full join b
on %eqfuzz(a.byval,b.byval);
create table d2 as
select a2.byval, a_val, b_val, a_group, b_group
from a2 full join b2
on a2.byval=b2.byval;
/**********************************************************************/