Следующая функция должна вычислять медиану 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
Столько ошибок в коде!
Я думаю, вы хотите:
#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];
}
}
Во-первых, если начальный вектор пуст, то, что вы делаете, небезопасно.
Во-вторых, ваша логика не верна в четном случае. Если 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]
}
Вам не нужен floor of ceil, вы можете сделать это намного эффективнее, используя целочисленную арифметику:
return (copyVec[copyVec.size()/2] + copyVec[(copyVec.size() + 1)/2]) / 2.0;
Теперь этот код будет работать так же, как ваш, но его легче читать и понимать.
Начните с опробования некоторых простых случаев и некоторых крайних случаев. В этом случае вы можете заметить, что ваш код не работает правильно для пустого массива.
Предположим, вы не видите ничего подозрительного в исследуемом коде. Лучше всего использовать отладчик. Иногда использование valgrind также поможет при повреждении стека.
Также вы можете рассмотреть возможность использования std::nth_element
для нахождения медианы вектора.