2014-10-23 2 views
3

Мой класс medianfilter.cpp вызывает qsort, как показано ниже.Ошибка компиляции сравнения qsort

vector<float> medianfilter::computeMedian(vector<float> v) { 
    float arr[100]; 
    std::copy(v.begin(), v.end(), arr); 

    unsigned int i; 
    qsort(arr, v.size(), sizeof(float), compare); 
    for (i = 0; i < v.size(); i++) { 
     printf("%f ", arr[i]); 
    } 
    printf("median=%d ", arr[v.size()/2]); 
    return v; 
} 

деле ввода моего сравнения:

int medianfilter::compare(const void * a, const void * b) { 
    float fa = *(const float*) a; 
    float fb = *(const float*) b; 
    return (fa > fb) - (fa < fb); 
} 

в то время как заявление в mediafilter.hpp устанавливается приватным и выглядит следующим образом:

int compare (const void*, const void*); 

ошибка компиляции происходит: cannot convert ‘mediafilter::compare’ from type ‘int (mediafilter::)(const void*, const void*)’ to type ‘__compar_fn_t {aka int (*)(const void*, const void*)}’

Я не понимаю эту ошибку полностью. Как правильно объявить и реализовать этот метод сравнения? Спасибо!

+0

Благодаря всем. Очень любезно даже просмотреть среднюю функцию (она на самом деле НЕ читалась. Извините, я никогда не должен публиковать не-смысл кода.) – feder

ответ

5

Сравните это не статическая функция-члена, тогда как QSort ожидает функцию, не являющийся члена (или статическую функцию-члена). Поскольку функция сравнения не использует каких-либо нестатических членов класса, вы можете просто объявить ее статичной. На самом деле я не уверен, что делает ваш средний класс фильтров вообще. Возможно, вам просто нужно пространство имен.

Почему бы не отсортировать вектор напрямую, а не копировать его во второй массив? Кроме того, ваш код будет разбит, если вектор содержит более 100 элементов.

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

Я также изменил тип возвращаемого значения вашей функции, потому что я не понимаю, почему функция называется computeMedian не возвратит медиану ..

namespace medianfilter 
{ 
    bool compare(float fa, float fb) 
    { 
     return fa < fb; 
    } 

    float computeMedian(vector<float> v) 
    { 
     std::sort(v.begin(), v.end(), compare); 
     // or simply: std::sort(v.begin(), v.end()); 
     for (size_t i = 0; i < v.size(); i++) { 
      printf("%f ", v[i]); 
     } 

     if (v.empty()) 
     { 
      // what do you want to happen here? 
     } 
     else 
     { 
      float median = v[v.size()/2]; // what should happen if size is odd? 
      printf("median=%f ", median); // it was %d before 
      return median; 
     } 
    } 
} 
4

Вы не можете вызвать сравнение, поскольку оно является функцией-членом и требует указателя this (то есть его нужно вызвать на объект). Однако, поскольку ваша функция сравнения не нуждается в указателе this, просто сделайте ее функцией static и ваш код будет скомпилирован.

Объявить его, как это в вашем классе:

static int compare(const void * a, const void * b); 
+2

Правильный трек, но ваш синтаксис плох. –

+0

@NeilKirk - вы правы - я вырезал и вставил его из своего теста, где у меня были функции, объявленные внутри класса, а затем «исправил» его вручную. Должно быть лучше сейчас. –

2

не связан с вашим вопросом (для которого вы уже есть ответ), но некоторые замечания:

  1. Ваш расчет медианы неправильный. Если количество элементов равно, вы должны вернуть среднее значение из двух значений центра, а не значение нижнего.
  2. Копия массива с установленным размером кричит переполнение буфера. Скопируйте на другой вектор и std: отсортируйте его или (как было предложено @NeilKirk) просто отсортируйте оригинал, если у вас нет причин не изменять его.
  3. Существует нет защиты от пустого ввода. Медиана не определена в этом случае, но ваша реализация будет просто вернуть все, что случается на обрах [0]
+2

(+1) Кроме того, вам не нужно вызывать sort() для вычисления медианы, вы можете уйти с одним вызовом nth_element() + один вызов min(), если число элементов четное. – user189035

+1

@ user189035 Интересно, мне было интересно, можно ли вычислить медиану без сортировки. –

+0

@NeilKirk см. Http://en.wikipedia.org/wiki/Partial_sorting –

2

Хорошо, это скорее приложение к Эле Algranti (отлично) ответа, чем ответ на первоначальный вопрос. ..пожалуйста, не уменьшайте до забвения;)

Вот общий код для вычисления квантиля quant вектора double, называемого x (который сохраняется ниже в коде).

Прежде всего: существует множество определений квантилей (только списки R 9). Код ниже соответствует определению # 5 (которое также является функцией квантиля по умолчанию в matlab и, как правило, те, о которых думают статистики, когда они думают о квантиле).

Основная идея заключается в том, что когда квантиль не попадает на точное наблюдение (например, когда вы хотите получить 15% квантилей массива длиной 10), реализация ниже реализует (правильную) интерполяцию (в этом случае между 10% и 20%) между соседним квантилем. Это важно, так что, когда вы увеличиваете количество наблюдений (i m намекает на имя medianfilter здесь), значение квантиля не скачкообразно скачкообразно, а сходится плавно (это одна из причин, почему это предпочтение статистиков).

Код предполагает, что x имеет хотя бы один элемент (код ниже является частью более длинного, и я чувствую, что этот момент уже сделан).

К сожалению, это написано с использованием многих функций из (отличной!) Электронной библиотеки C++, и мне слишком поздно в это передовое время в ночное время, чтобы перевести собственные функции - или дезинформировать имена переменных -, но ключевые идеи должны быть читаемыми.

#include <Eigen/Dense> 
#include <Eigen/QR> 

using namespace std; 
using namespace Eigen; 
using Eigen::MatrixXd; 
using Eigen::VectorXd; 
using Eigen::VectorXi; 

double quantiles(const Ref<const VectorXd>& x,const double quant){ 
//computes the quantile 'quant' of x. 
    const int n=x.size(); 
    double lq,uq,fq; 
    const double q1=n*(double)quant+0.5; 
    const int index1=floor(q1); 
    const int index2=ceil(q1); 
    const double index3=(double)index2-q1; 
    VectorXd x1=x; 
    std::nth_element(x1.data(),x1.data()+index1-1,x1.data()+x1.size()); 
    lq=x1(index1-1); 
    if(index1==index2){ 
     fq=lq; 
    } else { 
     uq=x1.segment(index1,x1.size()-index1-1).minCoeff(); 
     fq=lq*index3+uq*(1.0-index3); 
    } 
    return(fq); 
} 

Таким образом, код использует один вызов nth_element, который имеет среднюю сложность O(n) [извините за sloppely с использованием большого O для среднего] и (при четном п) один дополнительный вызов мин() [который по собственному диалекту отмечено .minCoeff()] на не более n/2 элементах вектора, который равен O (n/2).

Это намного лучше, чем при использовании частичного рода (который будет стоить O (NLog (п/2)), worst case) или сортировки (который будет стоить O(nlogn))

Смежные вопросы