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

 

sas-innovate-white.png

Register Today!

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.

Register now!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 1013 views
  • 4 likes
  • 4 in conversation