How do you calculate a percentage from 2 int values into a int value that represents a percentage(perthousands for more accuracy)?
Background/purpose: using a processor that doesn't have a FPU, floating point computations take 100's of times longer.
int x = 25;
int y = 75;
int resultPercentage; // desire is 250 which would mean 25.0 percent
resultPercentage = (x/(x+y))*1000; // used 1000 instead of 100 for accuracy
printf("Result= ");
printf(resultPercentage);
output:
Result= 0
When really what I need is 250. and I can't use ANY Floating point computation.
Example of normal fpu computation:
int x = 25;
int y = 75;
int resultPercentage; // desire is 250 which would mean 25.0 percent
resultPercentage = (int)( ( ((double)x)/(double(x+y)) ) *1000); //Uses FPU slow
printf("Result= ");
printf(resultPercentage);
output:
Result= 250
But the output came at the cost of using floating point computations.
resultPercentage = (x/(x+y))*1000;
does not work as(x/(x+y))
is likely0
or1
before the multiplcation*1000
occurs. Instead:For a rounded unsigned integer calculation of
x/(x+y)
, leta = x
andb = x+y
then to finda/b
use:For a rounded unsigned integer percent % calculation of
a/b
useFor a rounded unsigned integer permil ‰ calculation of
a/b
useFor a rounded unsigned integer permyriad ‱ calculation of
a/b
use@H2CO3 wells points out the concerns about eating up the integer range so using wider integers (
long
,long long
) are needed for the multiplication and maybex+y
.Of course, replace
A slight modification of expression can do the trick. Like in this case :
resultPercentage = (x*1000)/(x+y); should do the job.
try this:
You could just write
if you care about correct rounding, and
if you don't.
You are talking about "percentages", but I noticed that you are multiplying by 1000, which results in perthousands. If that's what you meant, then of course you'll need to change the multiplication factors to 10000 and 1000, respectively.
Furthermore, using integers significantly reduces the valid range of values to perform the computation on. This can be a bit widened if you force the intermediate results to be of a longer type, notably (signed or unsigned)
long long
:should do the trick (due to integer promotion).
A solution using long division
And now for the pencil-and-paper answer… Not sure if this will be faster than your processor's built in floating point arithmetic, but it's a fun thing to look at (and maybe improve upon). This is an implementation of long division (remember that?) - in principle it is "infinitely precise", a bit like BigDecimal math - in practice it is limited because a finite amount of space is allocated for the string (you could change that with a
malloc/free
). If you have trouble with (code) space on your processor (as well as the lack of a dedicated floating point unit) then this is definitely not the way to go; also I am assuming that all division (even integer) would be slow, and using only multiplication, addition and subtraction.Final bonus - the result comes out as a string, saving the need for a separate
printf
style conversion later. There are many ways conceivable for speeding this up; for now it's just fun to see how you can solve this problem with only limited precision integers, yet get a "very good" answer. Incidentally, according to my pedestrian timing code, the result is faster than a divide-and-sprintf routine (which was pretty gratifying). Almost certainly due to the fact that the conversion to a string of digits is happening "almost for free" (if you think about how that is normally done, it takes lots of division/modulo math…).EDIT in its current form, this code even takes account of rounding (computing one additional digit, and then making the necessary adjustments). One caveat: it only works for positive integers.
Play with it and tell me if you like it!
The result (without optimization turned on):
Why dont you use