Деление с точностью до 1 знака после запятой без математики с плавающей запятой? - PullRequest
2 голосов
/ 11 апреля 2010

У меня возникли проблемы со скоростью в моей программе на C #, и я обнаружил, что этот процентный расчет вызывает замедление. Вычисление просто n / d * 100. И числитель, и знаменатель могут быть любым целым числом. Числитель никогда не может быть больше знаменателя и никогда не бывает отрицательным. Поэтому результат всегда от 0 до 100. Прямо сейчас это делается простым использованием математики с плавающей запятой и несколько медленным, так как рассчитывается десятки миллионов раз. Мне действительно не нужно ничего более точного, чем с точностью до 0,1 процента. И я просто использую это вычисленное значение, чтобы увидеть, если оно больше, чем фиксированное постоянное значение. Я думаю, что все должно быть целым числом, поэтому диапазон с точностью 0,1 будет 0-1000. Есть ли способ рассчитать этот процент без математики с плавающей запятой?

Вот цикл, который я использую для расчета:

for (int i = 0; i < simulationList.Count; i++)
{
    for (int j = i + 1; j < simulationList.Count; j++)
    {
        int matches = GetMatchCount(simulationList[i], simulationList[j]);
        if ((float)matches / (float)simulationList[j].Catchments.Count > thresPercent)
        {
            simulationList[j].IsOverThreshold = true;
        }
    }
}

Ответы [ 3 ]

6 голосов
/ 11 апреля 2010

Вместо n/d > c вы можете использовать n > d * c (предположим, что d > 0).
(c - это постоянная величина, с которой вы сравниваете.)

Таким образом, вам вообще не нужно деление.

Однако, следите за переполнением.

0 голосов
/ 03 февраля 2015

Вместо записи

if ((float)matches / (float)simulationList[j].Catchments.Count > thresPercent)

напишите это:

if (matches * theresPercent_Denominator > simulationList[j].Catchments.Count * thresPercent_Numerator)

Таким образом вы избавляетесь от плавающих точек.

Примечание: thresPercent можно выразить как thresPercent_Numerator / theresPercent_Denominator, если число является рациональным числом.) Я думаю, что это оптимальный способ для ПК. Для какой-либо другой платформы вы можете дополнительно оптимизировать ее с помощью сдвига влево или вправо, если theresPercent_Denominator и / или thresPercent_Numerator имеют степень 2. (Обычно достаточно сдвига влево, но может потребоваться сдвиг вправо путем перестановки уравнения к делению, чтобы предотвратить переполнение)

0 голосов
/ 11 апреля 2010

Если ваши единицы в десятых долях, а не в единицах, то вы можете получить точность 0,1 с помощью целочисленной арифметики:

Вместо:

for (...)
{
    float n = ...;
    float d = ...;

    if (n / d > 1.4) // greater than 140% ?

... сделать что-то вроде:

for (...)
{
    int n = 10 * ...;
    int d = ...;
    if (n / d > 14) // greater than 140% ?
...