В этом руководстве мы рассмотрим, как использовать переменные аргументы в C для реализации процентильных функций. Процентиль — это статистический термин, который относится к показателю, ниже которого падает определенный процент данных. Например, 90-й процентиль набора данных — это значение, ниже которого находится 90 % данных.

Прежде чем мы углубимся в реализацию процентильных функций в C, давайте сначала разберемся с концепцией переменных аргументов.

Переменные аргументы в C

Переменные аргументы в C позволяют функции принимать различное количество аргументов. Эти типы функций полезны в случаях, когда мы не знаем точное количество аргументов, которые будут переданы функции во время компиляции. Функция переменных аргументов в C реализована с использованием заголовочного файла stdarg.h.

Заголовочный файл stdarg.h содержит макросы и функции для обработки переменных аргументов. Макросы: va_start, va_arg и va_end. va_start macro инициализирует указатель аргумента, va_arg macro извлекает следующий аргумент, а va_end macro освобождает все ресурсы, используемые указателем аргумента.

Теперь, когда у нас есть общее представление о переменных аргументах, давайте перейдем к реализации процентильных функций в C.

Реализация процентильных функций в C

Для целей этого руководства мы будем реализовывать две функции процентиля — одну для вычисления n-го процентиля, а другую — для вычисления медианы.

Функция n-го процентиля

Функция n-го процентиля принимает два аргумента — значение процентиля и переменное количество точек данных. Функция возвращает значение n-го процентиля.

#include <stdarg.h>

double nth_percentile(int n, int count, ...)
{
    int i, j;
    double temp, percentile;
    double* array = malloc(count * sizeof(double));
    va_list args;

    va_start(args, count);
    for (i = 0; i < count; i++)
    {
        array[i] = va_arg(args, double);
    }
    va_end(args);

    for (i = 0; i < count; i++)
    {
        for (j = i + 1; j < count; j++)
        {
            if (array[j] < array[i])
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }

    percentile = ((double)n / 100) * (count - 1) + 1;
    if (percentile == (int)percentile)
    {
        return array[(int)percentile - 1];
    }
    else
    {
        int k = (int)percentile;
        double d = percentile - k;
        return array[k - 1] + d * (array[k] - array[k - 1]);
    }
}

Пройдемся по реализации шаг за шагом.

  1. Начнем с объявления функции 1, которая принимает два аргумента — n и count — и многоточие (три точки), указывающее, что функция принимает переменное количество аргументов.
  2. Затем мы объявляем переменные i, j, temp, процентиль и массив. Переменная массива представляет собой динамически выделяемый массив двойников для хранения точек данных.
  3. Затем мы используем тип данных va_list для объявления указателя аргумента, args.
  4. Макрос va_start используется для инициализации указателя аргумента args с помощью аргумента count.
  5. Затем мы используем цикл for для перебора переменных аргументов и сохранения их в массиве.
  6. Макрос va_end используется для освобождения любых ресурсов, используемых указателем аргумента, args.
  7. Затем мы используем вложенный цикл for для сортировки точек данных в порядке возрастания.
  8. Мы вычисляем значение процентиля, используя следующую формулу: ((double)n / 100) * (count — 1) + 1. Эта формула основана на определении процентиля.
  9. Мы проверяем, является ли значение процентиля целым числом. Если это так, мы возвращаем точку данных по этому индексу в отсортированном массиве. Если это не так, мы интерполируем между двумя точками данных, чтобы получить значение процентиля.
  10. Наконец, мы освобождаем память, выделенную для переменной массива, и возвращаем значение процентиля.

Медианная функция

Медианная функция принимает переменное количество точек данных в качестве аргументов и возвращает медианное значение. Медиана — это значение, которое отделяет нижнюю половину набора данных от верхней половины.

double median(int count, ...)
{
    double* array = malloc(count * sizeof(double));
    int i, j;
    double temp, median;
    va_list args;

    va_start(args, count);
    for (i = 0; i < count; i++)
    {
        array[i] = va_arg(args, double);
    }
    va_end(args);

    for (i = 0; i < count; i++)
    {
        for (j = i + 1; j < count; j++)
        {
            if (array[j] < array[i])
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }

    if (count % 2 == 0)
    {
        median = (array[count / 2 - 1] + array[count / 2]) / 2;
    }
    else
    {
        median = array[count / 2];
    }

    free(array);
    return median;
}

Реализация функции медианы аналогична реализации функции n-го процентиля, с той лишь разницей, что мы не принимаем значение процентиля в качестве аргумента.

  1. Начнем с объявления функции median, которая принимает один аргумент — count — и многоточие (три точки), указывающее, что функция принимает переменное количество аргументов.
  2. Затем мы объявляем переменные i, j, temp, медиана и массив. Переменная массива представляет собой динамически выделяемый массив двойников для хранения точек данных.
  3. Затем мы используем тип данных va_list для объявления указателя аргумента, args.
  4. Макрос va_start используется для инициализации указателя аргумента args с помощью аргумента count.
  5. Затем мы используем цикл for для перебора переменных аргументов и сохранения их в массиве.
  6. Макрос va_end используется для освобождения любых ресурсов, используемых указателем аргумента, args.
  7. Затем мы используем вложенный цикл for для сортировки точек данных в порядке возрастания.
  8. Мы проверяем, является ли количество точек данных четным или нечетным. Если оно четное, мы берем среднее значение двух средних значений в качестве медианы. Если это нечетно, мы принимаем среднее значение как медиану.
  9. Наконец, мы освобождаем память, выделенную для переменной массива, и возвращаем медианное значение.

Заключение

В этом руководстве мы рассмотрели, как использовать переменные аргументы в C для реализации процентильных функций. Мы реализовали две функции — функцию n-го процентиля и функцию медианы — используя заголовочный файл stdarg.h.

Переменные аргументы — мощная функция языка C, которая позволяет нам писать более гибкие и универсальные функции. Немного попрактиковавшись, вы сможете начать включать переменные аргументы в свои собственные программы на C.