Страницы

Поиск по вопросам

среда, 27 ноября 2019 г.

Что такое предикатная функция?

#c++ #функции #предикат


Изучаю С++. В литературе одну из функций назвали предикатной. Что это может значить,
или это такой перевод ?
    


Ответы

Ответ 1



Давайте рассмотрим такую задачу. У нас есть, скажем, вектор целых чисел, и мы хотим вывести на экран только положительные числа. Как мы это сделаем? void out(const vector& v) { for(auto i: v) if (i > 0) cout << i << " "; } А если вывести все, больше 5? void out(const vector& v) { for(auto i: v) if (i > 5) cout << i << " "; } Похоже? Да. Так и тянет объединить их в void out(const vector& v, int value) { for(auto i: v) if (i > value) cout << i << " "; } Но что, если мы захотим вывести только четные? Только те, для которых синус положителен? Все это можно обобщить, например, так: void out(const vector& v, bool(*)(int) pred) { for(auto i: v) if (pred(i)) cout << i << " "; } Где pred - функция, которая проверяет некоторое условие, предикат. И будут выведены только те числа, для которых функция pred вернет значение true. А как мы ее напишем - наше дело. Например, bool pred(int i) { return i > 5; } Вот, по сути, и все. Остальное - функция, или лямбда, шаблон или нет, от скольки аргументов и т.д. и т.п. - не суть важно. Предикативная функция - проверяющая некоторое условие, предикат, для своего(их) аргумента(ов). Ну и - предикаты весьма широко применяются в алгоритмах стандартной библиотеки.

Ответ 2



Предикатом называется функция, возвращающая тип bool (или другое значение, которое может быть автоматически преобразовано к bool). Предикаты широко используются в STL. В частности, функции сравнения в стандартных ассоциативных контейнерах представляют собой предикаты. Предикатные функции часто передаются в виде параметров таким алгоритмам, как find_if, и различным алгоритмам сортировки. Источник.

Ответ 3



Вот написал небольшой пример. #include #include template T* array_move(T* fa, T* la, Cmp cmp){ T* p; while((fa != la) && cmp(*fa)) ++fa; for(p = fa; fa != la; ++fa){ if(cmp(*fa)){ std::swap(*fa, *p); ++p; } } return p; } int main(void){ std::ostream_iterator _out(std::cout, " "); int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int n = sizeof(a)/sizeof(a[0]); //переставить в начало массива чётные числа auto e1 = array_move(a, a + n, [] (int x) { return ((x & 1) == 0); }); std::copy(a, e1, _out); std::cout << std::endl; //переставить в начало массива только те числа которые кратны трём auto e2 = array_move(a, a + n, [] (int x){ return ((x % 3) == 0); }); std::copy(a, e2, _out); std::cout << std::endl; //переставить в начало массива только те числа у которых включен 3-ий бит auto e3 = array_move(a, a + n, [] (int x){ return (((x >> 2) & 1) == 1); }); std::copy(a, e3, _out); return 0; } И какой можно сделать вывод о предикате неважно как он выполнен структурой, функцией или лямдой? И так, предикат это условие которые встраивается из вне, тем самым позволяя функции быть более функциональной по сравнению с функциями без предикатов. Даже малейшего взгляда на код достаточно увидеть преимущество использования предиката, ибо без него пришлось писать мне три разные функции для выполнения задания, а если заданий будет 40? К примеру переместить в начало массива: простые числа числа Фибоначчи нечётные числа отрицательные числа положительные числа числа которые больше 100 но меньше 500 числа у которых включено 5-бит ...

Комментариев нет:

Отправить комментарий