开发者

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

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? Some开发者_运维百科thing that does not involve casting?


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


The right integer-only way to get percentage with proper rounding is:

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

How do we get there? If we do this thing in floating point, it would be Math.Floor( mappedItems * 100.0 / totalItems + 0.5 ). We need to transform this formula to be integer-only by multiplying and dividing 0.5 by totalItems, then moving 0.5 * totalItems into dividend, and then multiplying both dividend and divisor by 2 to make fractions go away:

mappedItems * 100.0 / totalItems + 0.5 => mappedItems * 100.0 / totalItems + totalItems * 0.5 / totalItems => ( mappedItems * 100.0 + 0.5 * totalItems ) / totalItems => ( mappedItems * 200.0 + totalItems ) / ( totalItems * 2 ).

At this point the formula is integer-only. When we do integer division, we get floored result, so the integer-only result is equivalent to the mentioned floating-point one.


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.


try this:

int mappedItems = someList.Count(x => x.Value != null);
int totalItems = someList.Count();
int percent = Convert.ToInt32(complete * 100.0 / total);

in this example, you'd get result being "50"

int mappedItems = 14;
int totalItems = 28;
int result = Convert.ToInt32(mappedItems * 100.0 / totalItems);
// result is 50


This is what works for me.

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

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜