BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
newboy1218
Quartz | Level 8

Hi, I am trying to calculate the % of A debt amount within the sum of A + B debt amount, and then I want to filter out % of A debt amount is between 90 - 100% (excluding 90% and 100%). However, in my result, it return answer where a_debt_pcent = 100.. Do you know why even though I excluded 100%?

 

Thanks.

 

 

data aa;
	input a_debt_amt b_debt_amt; 
	datalines;
	10701.54 0
	84256.96 0
	21462.54 0
	240 20
	23876.83 0
	95 5
	396 184
	982 3874
	0 9128
;
run;

data bb;
	set aa;
	a_debt_pcent = 100*a_debt_amt/(a_debt_amt+b_debt_amt);
	if 90 < a_debt_pcent < 100;
run;

WANT:

 

a_debt_amtb_debt_amta_debt_pcent
2402092.307692308
95595

 

What I am getting (I don't want that, it is wrong):

a_debt_amtb_debt_amta_debt_pcent
10701.540100
84256.960100
2402092.307692308
23876.830100
95595
1 ACCEPTED SOLUTION

Accepted Solutions
mkeintz
PROC Star

You have run into a numeric precision problem that arises from floating point calculations. This is NOT a SAS problem.  It is a problem of numeric representation on digital computers.

 

In effect, your statement:

	a_debt_pcent = 100*a_debt_amt/(a_debt_amt+b_debt_amt);

is calculated like this

	a_debt_pcent = (100*a_debt_amt)/(a_debt_amt+b_debt_amt);

 

That is, it makes the product  100*a_debt_amt for the numerator first, then sums a_debt_amt and b_debt_amt for denominator, then divides.  The problem is that the numeric representation of 100*a_debtamt, will not always yield a value of 100 when divided by a_debt_amt  (i.e. when b_debt_amt=0).  You will see "100" because it is not printing with enough precision to show the very minor difference from 100 that might occur.

 

Change the statement to 

	 a_debt_pcent = 100* (a_debt_amt/(a_debt_amt+b_debt_amt));

Then you will always get 100 when b_debt_amt is zero.  

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

View solution in original post

3 REPLIES 3
mkeintz
PROC Star

You have run into a numeric precision problem that arises from floating point calculations. This is NOT a SAS problem.  It is a problem of numeric representation on digital computers.

 

In effect, your statement:

	a_debt_pcent = 100*a_debt_amt/(a_debt_amt+b_debt_amt);

is calculated like this

	a_debt_pcent = (100*a_debt_amt)/(a_debt_amt+b_debt_amt);

 

That is, it makes the product  100*a_debt_amt for the numerator first, then sums a_debt_amt and b_debt_amt for denominator, then divides.  The problem is that the numeric representation of 100*a_debtamt, will not always yield a value of 100 when divided by a_debt_amt  (i.e. when b_debt_amt=0).  You will see "100" because it is not printing with enough precision to show the very minor difference from 100 that might occur.

 

Change the statement to 

	 a_debt_pcent = 100* (a_debt_amt/(a_debt_amt+b_debt_amt));

Then you will always get 100 when b_debt_amt is zero.  

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
average_joe
Obsidian | Level 7

Round your percent calculation to the nearest whole number like this:

	a_debt_pcent = round(100*a_debt_amt/(a_debt_amt+b_debt_amt), 1);

The reason has to do with numeric precision and floating point math. You can read about it here.

 

Try this as another example:

 

data _null_;
num = .1 * 3;

if num = .3 then put '1. Equal';
else put '1. Not Equal';

if round(num, .1) = .3 then put '2. Equal';
else put '2. Not Equal';
run;
Sajid01
Meteorite | Level 14

Hello @newboy1218 

Simple and self-explanatory changes to your code will give you the desired result.

Your a_dept_pcent is a floating point number. Hence the small changes to your expressions..

data bb;
	set aa;
	a_debt_pcent = round((100*a_debt_amt)/(a_debt_amt+b_debt_amt),2);
	format a_debt_pcent z6.3;
	if 90.000 < a_debt_pcent < 100.000;
run;

The output is what you want

Sajid01_0-1650982931882.png

 

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 3 replies
  • 571 views
  • 4 likes
  • 4 in conversation