Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Вычисление процентов трех величин чья сумма = 100%


Автор: santey 20.9.2010, 22:50
Имеются 3 величины, которые в сумме составляют 100 процентов

первая - 1000
вторая - 38
третья - 20 

необходимо точно вычислить какой процент составляет каждая величина от общей суммы.

для этого сложим 3 суммы и умножим на 0.01 и получим величину одного процента,
которая равна 10.58, далее каждую величину разделим на один процент и получим

первая - 94.5179
вторая -  3.5916
третья -  1.8903

так вот как эти величины правильно округлить так, чтобы получились правильные значения
в процентах переменной в int?


Если округлять вверх то получится
первая - 95%
вторая -  4%
третья -  2%
здесь 95+4+2=101%  неправильно

Если округлять вниз то получится
первая - 94%
вторая -  3%
третья -   1%
здесь 94+3+1=98% тоже неправильно

Может быть имеются функции выделяющие правильный процент из определенной величины?
                

Автор: ИванМ 20.9.2010, 23:03
Цитата(santey @  20.9.2010,  22:50 Найти цитируемый пост)
так вот как эти величины правильно округлить так, чтобы получились правильные значения
в процентах переменной в int?

Вычислить то, что на самом деле, потом понизить ту величину, у которой дробная часть самая маленькая.

Цитата(santey @  20.9.2010,  22:50 Найти цитируемый пост)
Может быть имеются функции выделяющие правильный процент из определенной величины?

Нет такой функции

Автор: casey 21.9.2010, 08:42
Я бы так сделал:

Округлить все числа вверх.

Если в сумме 102 - 2 числа с наименьшей дробной частью округлять вниз, оставшееся вверх.
    если в сумме 101 - 1 число с наименьшей дробной часть округлять вниз , оставшиеся 2 вверх.
    если в сумме 100 - все числа округлять вверх (или вниз как нравится - потому что 100 получится только когда все числа целые)           

Автор: t4aynik 23.9.2010, 16:33
100*1000/(1000+38+20)=~95%
(100-95)*38/(38+20)=~3%
100-95-3=2%

то что с ~ округляй как хочешь.
так не пойдет?

Автор: santey 23.9.2010, 18:48
Цитата(t4aynik @ 23.9.2010,  16:33)
100*1000/(1000+38+20)=~95%
(100-95)*38/(38+20)=~3%
100-95-3=2%

то что с ~ округляй как хочешь.
так не пойдет?

Конечно не пойдет.

А как узнать в какую сторону округлять? в большую или меньшую.
Имею в виду первое число ~95

Автор: santey 23.9.2010, 19:50
Цитата(ИванМ @  20.9.2010,  23:03 Найти цитируемый пост)
Вычислить то, что на самом деле, потом понизить ту величину, у которой дробная часть самая маленькая.



Данный способ не работает, если 2 величины имеют равное значение.

Автор: ИванМ 24.9.2010, 00:07
Вот что пока получилось. Страшно, ужасно и коряво, но вроде работает.
Код

#include <iostream>
#include <algorithm>

bool less(double* v1, double* v2)
{
    return (*v1-(int)(*v1))<(*v2-(int)(*v2));
}

bool great(double* v1, double* v2)
{
    return (*v1-(int)(*v1))>(*v2-(int)(*v2));
}

void go(double* v1, double* v2, double* v3)
{
    double *arr[3]={v1, v2, v3};
    double v=0.01*((*v1)+(*v2)+(*v3));
    for(size_t i=0;i<3;++i)
    {
        (*arr[i])=((*arr[i])/v);
    }

    int val=((int)(*arr[0])+(int)(*arr[1])+(int)(*arr[2]));
    if(val>100)
        std::sort(arr, arr+3, less);
    else if(val<100)
        std::sort(arr, arr+3, great);
    else
    {
        *arr[0]=(int)(*arr[0]);
        *arr[1]=(int)(*arr[1]);
        *arr[2]=(int)(*arr[2]);
        return;
    }

    size_t pos=0;

    while(true)
    {
        int val=((int)(*arr[0])+(int)(*arr[1])+(int)(*arr[2]));

        if(val>100)
        {
            --(*arr[pos]);
            ++pos;
        }
        else if(val<100)
        {
            ++(*arr[pos]);
            ++pos;
        }
        else
        {
            *arr[0]=(int)(*arr[0]);
            *arr[1]=(int)(*arr[1]);
            *arr[2]=(int)(*arr[2]);
            return;
        }
    }
}

int main(int argc, char* argv[])
{
    double v1=1000, v2=38, v3=20;
    std::cout<<v1<<" "<<v2<<" "<<v3<<std::endl;
    go(&v1, &v2, &v3);
    std::cout<<v1<<" "<<v2<<" "<<v3<<std::endl;
    std::system("pause");
    return 0;
}


Автор: t4aynik 24.9.2010, 09:00
Цитата(santey @  23.9.2010,  18:48 Найти цитируемый пост)
А как узнать в какую сторону округлять? в большую или меньшую.Имею в виду первое число ~95

smile
По правилам математики: 94.7 = 95, 95.3 = 95.
а вообще вы вносите неплохую погрешность преобразуя результаты к целому.

Автор: santey 24.9.2010, 22:25
Все варианты перебрал и либо громоздкая функция, вычисляющая целые проценты или же очень простая но дающая 100 процентные проценты это double с одним значением после запятой.

Например, для своей программы сделал

double TFormMain::Procent(int S[3],int number)
{
   //определяем процент значения number
   double pr_number=(double)S[number]/((S[0]+S[1]+S[2])*0.01);      

   //отделяем дробную часть и переводим в целое число
   int a=Frac(pr_number)*1000;        

   //отделяем по значению и округляем его, если надо                       
   for(int i=0;i<2;i++)        a=a/10+(fmod(a,10)>5 ? 1 : 0);

   //возвращаем полученный результат
   return floor(pr_number)+a*0.1;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)