Can somebody who has used both R and SAS provide some insights
SAS numeric are 8-bytes floats. On my windows machine, the largest consecutive integer in SAS is
9,007,199,254,740,992. (= constant('exactint',8).
Call it X.
Then, given that data are stored as binary mantissa and binary exponent.
Similarly:
You can work your way down to any base-2 level of precision to show this asymmetry of precision surrounding X times some power of 2.
But back to your problem as stated - rounding to the tenth does not produced expected value:
filename values temp;
data _null_; /* Write out starting and expected round */
file values;
put 'datalines;';
length value expect $15;
do ndigits=1 to 10;
value=cats(repeat('9',ndigits),.15);
expect=cats(repeat('9',ndigits),.2);
put value= expect=;
end;
put 'run;';
run;
data oops; /* Read starting and expected value, calculate round and check */
input value= expect=;
check=round(value,.1);
format value expect check comma22.2;
if check^=expect then flag='OOPS';
%include values;
run;
proc print;
run;
Notice OOPS flag is on for a couple numbers generated above.
I think your friend's assumption about representable numbers is incorrect.
I think you are seeing that R (and more recently, Python) adopted the engineering convention of “round to even” when rounding off a 5. See the documentation for the round function in r: ?round
SAS rounds 5 away from 0. See Rounding up, rounding down
I suspect the "round to even" approach is a way to eliminate bias in rounding for samples with well-behaved distributions at the larger order of magnitude. Ceteris paribus, it would round up and down about the same number of times.
But over here in the academic financial analysis world, our users would be mighty surprised, and often annoyed, if 5 were not rounded up.
I suppose you could work around each of these behaviors to produce the other,
I can't find "round half to even" in the blog you've posted. I guess it would need some formula along the line of below.
data test;
input have expected;
even=mod(int(have)+1,2);
dot5=abs(mod(have,1))=0.5;
calculated=round(have) - (even * dot5);
calculated2= round(have) - mod(int(have)+1,2) * (abs(mod(have,1))=0.5);
correct= expected=calculated;
datalines;
23.49 23
23.50 24
23.51 24
23.99 24
24.00 24
24.01 24
24.49 24
24.50 24
24.51 25
-23.49 -23
-23.50 -24
-23.51 -24
-23.99 -24
-24.00 -24
-24.01 -24
-24.49 -24
-24.50 -24
-24.51 -25
;
proc print;
run;
No, it's much easier. Just use the ROUNDE function. The 'E' in the name is for "round to Even".
For more information about the round-to-even method, including examples of using the ROUNDE function in SAS, see the article "Round to even."
Does R support rounding to values like 0.7?
Such as:
data example; do i= 1 to 2 by 0.01; y= round(i,0.7); output; end; run;
Not via the standard round() function. It rounds to powers of 10.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Need to connect to databases in SAS Viya? SAS’ David Ghan shows you two methods – via SAS/ACCESS LIBNAME and SAS Data Connector SASLIBS – in this video.
Find more tutorials on the SAS Users YouTube channel.