What's the best way to create a percentage value from two integers in C#?

Viewed 58596

I have two integers that I want to divide to get a percentage.

This is what I have right now:

int mappedItems = someList.Count(x => x.Value != null);
int totalItems = someList.Count();
(int)(((double)mappedItems /(double) totalItems) * 100)

This gives the right answer. But that is a lot of casting to do something as simple as get a percentage between two numbers.

Is there a better way to do this? Something that does not involve casting?

9 Answers

How about just mappedItems * 100.0 / totalItems and casting this to the appropriate type?

If you just wanted to avoid the casts, you could write:

(100 * mappedItems) / totalItems

but that will quickly overflow when mappedItems > int.MaxValue / 100.

And both methods round the percentage down. To get correct rounding, I would keep the result as a double:

((double)mappedItems /(double) totalItems) * 100

You can get a correctly rounded result using only integer operations:

int percent = (200 * mappedItems + 1) / (totalItems * 2);

By multiplyingby two, adding one and dividing by two, you are effectively adding a half. This makes the integer division do a rounding instead of truncating.

Well, assuming your counts are smaller than int.MaxValue:

int percent = mappedItems * 100 / totalItems;

You could use (mappedItems * 100) / totalItems but this would always round down. The method that you have used is better. Why not wrap the code up as a method?

Just to add that as you've got ints and want to calculate the percentage (a floating point value) you are going to have to do casting. Whether it's explicit as in C# or implicit as in some scripting languages the cast will still happen. It's better to make it explicit.

If you want fewer casts per line of code you could write:

double mappedItems = (double)someList.Count(x => x.Value != null);
double totalItems = (double)someList.Count();
double percentage = (mappedItems / totalItems) * 100.0);

Though as others have pointed out - check for totalItems being 0 (preferably before casting to double) to avoid a divide by zero.

This is what works for me.

 double percentage = (double) (mappedietms * 100) / totalitems;

label6.Text = $@"Health: [{Math.Round(percentage ,1)}]";

Related