Ответ 1
Как насчет только mappedItems * 100.0 / totalItems
и отбрасывая это на соответствующий тип?
У меня есть два целых числа, которые я хочу разделить, чтобы получить процент.
Вот что я имею прямо сейчас:
int mappedItems = someList.Count(x => x.Value != null);
int totalItems = someList.Count();
(int)(((double)mappedItems /(double) totalItems) * 100)
Это дает правильный ответ. Но это много кастингов, чтобы сделать что-то так же просто, как получить процент между двумя числами.
Есть ли лучший способ сделать это? Что-то, что не связано с кастингом?
Как насчет только mappedItems * 100.0 / totalItems
и отбрасывая это на соответствующий тип?
Правильный целочисленный способ получить процент с правильным округлением:
int result = ( mappedItems * 200 + totalItems ) / ( totalItems * 2 );
Как мы туда доберемся? Если мы будем делать это в плавающей точке, это будет Math.Floor( mappedItems * 100.0 / totalItems + 0.5 )
. Нам нужно преобразовать эту формулу в целое число - только путем умножения и деления на 0,5 по суммам, затем перемещения 0,5 * totalItems в дивиденды, а затем умножения как дивидендов, так и делителей на 2 для удаления фракций:
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).
В этот момент формула является целым числом. Когда мы выполняем целочисленное деление, мы получаем результат с полом, поэтому результат с целым числом эквивалентен упомянутому плавающему пункту.
Если вы просто хотите избежать прикладов, вы можете написать:
(100 * mappedItems) / totalItems
но это будет быстро переполняться, когда mappedItems > int.MaxValue / 100
.
И оба метода округляют процент вниз. Чтобы получить правильное округление, я бы сохранил результат как двойной:
((double)mappedItems /(double) totalItems) * 100
Вы можете получить правильно округленный результат, используя только целые операции:
int percent = (200 * mappedItems + 1) / (totalItems * 2);
Путем умножения на два, добавив одно и разделив на два, вы фактически добавляете половину. Это делает целочисленное деление делать округление вместо усечения.
Ну, если ваши подсчеты меньше, чем int.MaxValue:
int percent = mappedItems * 100 / totalItems;
Вы можете использовать (mappedItems * 100)/totalItems, но это всегда будет округлено. Метод, который вы использовали, лучше. Почему бы не обернуть код как метод?
Просто добавьте, что, поскольку у вас есть int
и вы хотите рассчитать процент (значение с плавающей запятой), вам придется делать кастинг. Является ли он явным, как в С# или неявным, как в некоторых языках сценариев, приведение в действие все равно произойдет. Лучше сделать это явным.
Если вам нужно меньше бросков на строку кода, вы можете написать:
double mappedItems = (double)someList.Count(x => x.Value != null);
double totalItems = (double)someList.Count();
double percentage = (mappedItems / totalItems) * 100.0);
Хотя, как указывали другие, проверьте, чтобы totalItems
равнялся 0 (предпочтительно перед литьем в два раза), чтобы избежать деления на ноль.
попробуйте следующее:
int mappedItems = someList.Count(x => x.Value != null);
int totalItems = someList.Count();
int percent = Convert.ToInt32(complete * 100.0 / total);
в этом примере вы получите результат: "50"
int mappedItems = 14;
int totalItems = 28;
int result = Convert.ToInt32(mappedItems * 100.0 / totalItems);
// result is 50