Вычисление медианы std :: vector & lt; double & gt; вызывая сегфо

Следующая функция должна вычислять медиану std::vector<double>,

double vecMed(vector<double>& vec) {

vector<double> copyVec = vec;

sort(copyVec.begin(), copyVec.end());

if( copyVec.size()%2 == 0)
return (copyVec[floor(static_cast<double>(copyVec.size())/2.0)] + copyVec[ceil(static_cast<double>(copyVec.size())/2.0)]) / 2.0;
else
return copyVec[copyVec.size()/2];
}

Я получаю сегфо на этой линии, иногда:

return (copyVec[floor(static_cast<double>(copyVec.size())/2.0)] + copyVec[ceil(static_cast<double>(copyVec.size())/2.0)]) / 2.0;

Кто-нибудь может увидеть проблему с этой функцией?

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


ГБД говорит:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000428ab6 in vecMed (this=0x7fffffffd1b0, vec=...) at ../globals.cpp:834
834         return (copyVec[floor(static_cast<double>(copyVec.size())/2.0)] + copyVec[ceil(static_cast<double>(copyVec.size())/2.0)]) / 2.0;
(gdb) bt
#0  0x0000000000428ab6 in vecMed (this=0x7fffffffd1b0, vec=...) at ../globals.cpp:834

2

Решение

Столько ошибок в коде!
Я думаю, вы хотите:

#include <algorithm>
#include <vector>

double vecMed(std::vector<double> vec) {
if(vec.empty()) return 0;
else {
std::sort(vec.begin(), vec.end());
if(vec.size() % 2 == 0)
return (vec[vec.size()/2 - 1] + vec[vec.size()/2]) / 2;
else
return vec[vec.size()/2];
}
}
8

Другие решения

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

Во-вторых, ваша логика не верна в четном случае. Если copyVec.size() % 2 == 0Равномерно, так static_cast<double>(copyVec.size())/2.0 является целым числом Итак, и пол, и потолок — это одно и то же, так что это, вероятно, не то, что вы хотите сделать. Предпочитаю что-то вроде:

const int mid = copyVec.size() / 2;
if (copyVec.size() % 2 == 0) {
return 0.5 * (copyVec[mid] + copyVec[mid+1]); // safe unless size == 0
}
else {
return copyVec[mid]; // e.g. if size == 3, return copyVec[1]
}
4

Вам не нужен floor of ceil, вы можете сделать это намного эффективнее, используя целочисленную арифметику:

return (copyVec[copyVec.size()/2] + copyVec[(copyVec.size() + 1)/2]) / 2.0;

Теперь этот код будет работать так же, как ваш, но его легче читать и понимать.
Начните с опробования некоторых простых случаев и некоторых крайних случаев. В этом случае вы можете заметить, что ваш код не работает правильно для пустого массива.

Предположим, вы не видите ничего подозрительного в исследуемом коде. Лучше всего использовать отладчик. Иногда использование valgrind также поможет при повреждении стека.

Также вы можете рассмотреть возможность использования std::nth_element для нахождения медианы вектора.

1
По вопросам рекламы [email protected]