BookmarkSubscribeRSS Feed
Babloo
Rhodochrosite | Level 12
I'm trying to compare the strings using strip function and that is not doing the comparison as I except.

IMO or in terms of project, value 253.3 or 253.30 or 253.0000000000 should be equal. However the following SAS code says it is not equal. I'm OK if the string is converted to numeric while we do the comparison in the following code but the condition is I have to preserve the format numx18.10.

Right now the following comparison is not equal but I want it to resolve it as equal.

If strip('253.3') ne strip(put(input('253.3',numx18.10),numx18.10))
then num_error=1;
6 REPLIES 6
Kurt_Bremser
Super User

Why are you treating numbers as strings? That is, to be very polite, not a bright thing to do.

If you want 253.3 and 253 to be equal, just do this:

data test;
input x y;
if round(x,1) = round(y,1)
then test = "yes";
else test = "no";
datalines;
253.3 253
;
Babloo
Rhodochrosite | Level 12
Any other way/functions without using round function? Because if I compare
253.311 with 253.312 then it should resolve as not equal. I will loose this
behavior if I use round function.
Babloo
Rhodochrosite | Level 12
Rule is you should get the value as 0 when you difference the two value.

E.g

253.3 and 253.300 should be equal.
253.3 and 253.3000 should be equal
253.312 and 253.313 is not equal
253.3 and 253.31 is not equal
Kurt_Bremser
Super User

Quote from your original post:

"IMO or in terms of project, value 253.3 or 253.30 or 253.0000000000 should be equal. "

 

Please proofread your posts, and edit them if you find such crucial mistakes.

 

But my basic point stays: Store numbers as NUMBERS, and you can make simple comparisons.

If not, input values to numbers, and compare those:

data test;
input x :$20. y :$20.;
if input(x,32.) = input(y,32.)
then test = "yes";
else test = "no";
datalines;
253.3 253
253.3 253.300000000
253.312 253.313
;

proc print data=test noobs;
run;

Result:

   x       y                test

253.3      253              no  
253.3      253.300000000    yes 
253.312    253.313          no  
FreelanceReinh
Jade | Level 19

Hi @Babloo,

 

I suspect the reason why you're doing this is that you encountered numeric representation issues.

 

Example:

data _null_;
x=253.3;
y=759.9/3;
put (x y)(/=25.20);
if x ne y then put 'different!';
run;

Result (with SAS 9.4M5 under Windows):

x=253.30000000000000000000
y=253.30000000000000000000
different!

So, it happens easily to obtain numbers which should be equal (mathematically) and which look equal (with common display formats), but SAS considers them different because of tiny rounding errors.

 

Similar issues can even occur without involving calculations, just by appending zeros to decimal fractions (see examples further below).

 

The standard way of dealing with said issues is using the ROUND function with a suitable rounding unit -- where "suitable" means: small enough not to influence results, but big enough to correct rounding errors in the least significant bits. It depends to some extent on the order of magnitude of the values to be rounded, but a value of 1E-9 is suitable for many practical applications.

 

Example:

data test;
input x;
r=round(x,1e-9);
cards;
1E-5
1.0E-5
1.00E-5
1.000E-5
253.3
253.3000000000000000000
253.30000000000000000000000
253.300000001
;

proc print data=test;
format x r hex16.;
run;

Result:

Obs                   x                   r

 1     3EE4F8B588E368F1    3EE4F8B588E368F1
 2     3EE4F8B588E368F0    3EE4F8B588E368F1
 3     3EE4F8B588E368F0    3EE4F8B588E368F1
 4     3EE4F8B588E368F1    3EE4F8B588E368F1
 5     406FA9999999999A    406FA9999999999A
 6     406FA99999999999    406FA9999999999A
 7     406FA9999999999B    406FA9999999999A
 8     406FA999999A230A    406FA999999A230A

Note how the ROUND function maps the different internal values of obs. 1 vs. 2 and obs. 3 vs. 4 to the same value. The same goes for obs. 5, 6 and 7 -- but without losing the ability to distinguish between values that differ by 1E-9 (the rounding unit), see obs. 8.

 

Edit: Your attempt using the NUMX18.10 (in)format must fail in general because a value displayed with this format will mostly have more than one decimal place (in fact up to 10 -- if space permits) and contain a comma rather than a decimal point, so it can't be equal to something like "253.3". Moreover, note that using the decimal specification (e.g. numx18.10) in the informat is risky because it causes a division of integers by a power of 10 and is ignored for values already containing a decimal point (or comma in this case).

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 1222 views
  • 2 likes
  • 3 in conversation