Computing median of std::vector<double> causing segfault - c++

The following function is supposed to compute the median of a 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];
}
I'm getting a segfault on this line, sometimes:
return (copyVec[floor(static_cast<double>(copyVec.size())/2.0)] + copyVec[ceil(static_cast<double>(copyVec.size())/2.0)]) / 2.0;
Can anyone see a problem with this function?
The segfault might be due to memory corruption elsewhere that I'm unaware of, but I want to make sure I'm not making a subtle or careless mistake in the above code before I explore that possibility.
GDB says:
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

So much errors in the code!
I guess you want:
#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];
}
}

First off, if the initial vector is empty, what you're doing is not safe.
Secondly, your logic isn't right in the even case. If copyVec.size() % 2 == 0, it's even, so static_cast<double>(copyVec.size())/2.0 is an integer. So both the floor and ceil are the same thing, so that's probably not what you want to do. Prefer something like:
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]
}

You don't need floor of ceil, you can do this far more efficiently using integer arithmetic:
return (copyVec[copyVec.size()/2] + copyVec[(copyVec.size() + 1)/2]) / 2.0;
Now this code will do the same as yours but it is easier to read and understand.
Start by trying out some simple cases and some edge cases. In this case you may note that your code does not run correctly for an empty array.
Lets assume you don't see anything suspicious in the code you investigate your best option is to use a debugger. Sometimes using valgrind would also help if you have a stack corruption.
Also you may want to consider using std::nth_element for finding the median of a vector.

Related

Rotate elements in a vector and how to return a vector

c++ newbie here. So for an assignment I have to rotate all the elements in a vector to the left one. So, for instance, the elements {1,2,3} should rotate to {2,3,1}.
I'm researching how to do it, and I saw the rotate() function, but I don't think that will work given my code. And then I saw a for loop that could do it, but I'm not sure how to translate that into a return statement. (i tried to adjust it and failed)
This is what I have so far, but it is very wrong (i haven't gotten a single result that hasn't ended in an error yet)
Edit: The vector size I have to deal with is just three, so it doesn't need to account for any sized vector
#include <vector>
using namespace std;
vector<int> rotate(const vector<int>& v)
{
// PUT CODE BELOW THIS LINE. DON'T CHANGE ANYTHING ABOVE.
vector<int> result;
int size = 3;
for (auto i = 0; i < size - 1; ++i)
{
v.at(i) = v.at(i + 1);
result.at(i) = v.at(i);
}
return result;
// PUT CODE ABOVE THIS LINE. DON'T CHANGE ANYTHING BELOW.
}
All my teacher does it upload textbook pages that explain what certain parts of code are supposed to do but the textbook pages offer NO help in trying to figure out how to actually apply this stuff.
So could someone please give me a few pointers?
Since you know exactly how many elements you have, and it's the smallest number that makes sense to rotate, you don't need to do anything fancy - just place the items in the order that you need, and return the result:
vector<int> rotate3(const vector<int>& x) {
return vector<int> { x[1], x[2], x[0] };
}
Note that if your collection always has three elements, you could use std::array instead:
std::array<int,3>
First, just pay attention that you have passed v as const reference (const vector<int>&) so you are forbbiden to modify the state of v in v.at(i) = v.at(i + 1);
Although Sergey has already answered a straight forward solution, you could correct your code like this:
#include <vector>
using namespace std;
vector<int> left_rotate(const vector<int>& v)
{
vector<int> result;
int size = v.size(); // this way you are able to rotate vectors of any size
for (auto i = 1; i < size; ++i)
result.push_back(v.at(i));
// adding first element of v at end of result
result.push_back(v.front());
return result;
}
Use Sergey's answer. This answer deals with why what the asker attempted did not work. They're damn close, so it's worth going though it, explaining the problems, and showing how to fix it.
In
v.at(i) = v.at(i + 1);
v is constant. You can't write to it. The naïve solution (which won't work) is to cut out the middle-man and write directly to the result vector because it is NOT const
result.at(i) = v.at(i + 1);
This doesn't work because
vector<int> result;
defines an empty vector. There is no at(i) to write to, so at throws an exception that terminates the program.
As an aside, the [] operator does not check bounds like at does and will not throw an exception. This can lead you to thinking the program worked when instead it was writing to memory the vector did not own. This would probably crash the program, but it doesn't have to1.
The quick fix here is to ensure usable storage with
vector<int> result(v.size());
The resulting code
vector<int> rotate(const vector<int>& v)
{
// PUT CODE BELOW THIS LINE. DON'T CHANGE ANYTHING ABOVE.
vector<int> result(v.size()); // change here to size the vector
int size = 3;
for (auto i = 0; i < size - 1; ++i)
{
result.at(i) = v.at(i + 1); // change here to directly assign to result
}
return result;
// PUT CODE ABOVE THIS LINE. DON'T CHANGE ANYTHING BELOW.
}
almost works. But when we run it on {1, 2, 3} result holds {2, 3, 0} at the end. We lost the 1. That's because v.at(i + 1) never touches the first element of v. We could increase the number of for loop iterations and use the modulo operator
vector<int> rotate(const vector<int>& v)
{
// PUT CODE BELOW THIS LINE. DON'T CHANGE ANYTHING ABOVE.
vector<int> result(v.size());
int size = 3;
for (auto i = 0; i < size; ++i) // change here to iterate size times
{
result.at(i) = v.at((i + 1) % size); // change here to make i + 1 wrap
}
return result;
// PUT CODE ABOVE THIS LINE. DON'T CHANGE ANYTHING BELOW.
}
and now the output is {2, 3, 1}. But it's just as easy, and probably a bit faster, to just do what we were doing and tack on the missing element after the loop.
vector<int> rotate(const vector<int>& v)
{
// PUT CODE BELOW THIS LINE. DON'T CHANGE ANYTHING ABOVE.
vector<int> result(v.size());
int size = 3;
for (auto i = 0; i < size - 1; ++i)
{
result.at(i) = v.at(i + 1);
}
result.at(size - 1) = v.at(0); // change here to store first element
return result;
// PUT CODE ABOVE THIS LINE. DON'T CHANGE ANYTHING BELOW.
}
Taking this a step further, the size of three is an unnecessary limitation for this function that I would get rid of and since we're guaranteeing that we never go out of bounds in our for loop, we don't need the extra testing in at
vector<int> rotate(const vector<int>& v)
{
// PUT CODE BELOW THIS LINE. DON'T CHANGE ANYTHING ABOVE.
if (v.empty()) // nothing to rotate.
{
return vector<int>{}; // return empty result
}
vector<int> result(v.size());
for (size_t i = 0; i < v.size() - 1; ++i) // Explicitly using size_t because
// 0 is an int, and v.size() is an
// unsigned integer of implementation-
// defined size but cannot be larger
// than size_t
// note v.size() - 1 is only safe because
// we made sure v is not empty above
// otherwise 0 - 1 in unsigned math
// Becomes a very, very large positive
// number
{
result[i] = v[i + 1];
}
result.back() = v.front(); // using direct calls to front and back because it's
// a little easier on my mind than math and []
return result;
// PUT CODE ABOVE THIS LINE. DON'T CHANGE ANYTHING BELOW.
}
We can go further still and use iterators and range-based for loops, but I think this is enough for now. Besides at the end of the day, you throw the function out completely and use std::rotate from the <algorithm> library.
1This is called Undefined Behaviour (UB), and one of the most fearsome things about UB is anything could happen including giving you the expected result. We put up with UB because it makes for very fast, versatile programs. Validity checks are not made where you don't need them (along with where you did) unless the compiler and library writers decide to make those checks and give guaranteed behaviour like an error message and crash. Microsoft, for example, does exactly this in the vector implementation in the implementation used when you make a debug build. The release version of Microsoft's vector make no checks and assumes you wrote the code correctly and would prefer the executable to be as fast as possible.
I saw the rotate() function, but I don't think that will work given my code.
Yes it will work.
When learning there is gain in "reinventing the wheel" (e.g. implementing rotate yourself) and there is also gain in learning how to use the existing pieces (e.g. use standard library algorithm functions).
Here is how you would use std::rotate from the standard library:
std::vector<int> rotate_1(const std::vector<int>& v)
{
std::vector<int> result = v;
std::rotate(result.begin(), result.begin() + 1, result.end());
return result;
}

C++ time limit exceeded when it doesn't even execute the function

While I was solving a problem in LeetCode, I found something very strange.
I have this line which I assume gives me a time limit exceeded error:
s.erase(i-k, k);
when I comment(//) this line, it doesn't show me time exceed error, but the strange part was, it has never executed even when i didn't comment it.
below is the entire code.
and Here is the problem link.
class Solution {
public:
string removeDuplicates(string s, int k) {
char prev = s[0];
int cnt = 1;
cnt = 1;
for(int i = 1; i < s.size() + 1; i++){
if(s[i] == prev){
cnt++;
} else {
if(cnt == k){
// when input is "abcd" it never comes to this scope
// which is impossible to run erase function.
s.erase(i-k, k);
i = 0;
}
if(i >= s.size()) break;
cnt = 1;
prev = s[i];
}
}
return s;
}
};
When Input is "abcd", it never even go to the if scope where 'erase' function is in.
Although 'erase' function never run, it still affect on the time complexity, and I can't get the reason.
Does anyone can explain this? or is this just problem of LeetCode?
Many online contest servers report Time Exceeding when program encounters critical error (coding bug) and/or crashes.
For example error of reading out of bounds of array. Or dereferencing bad (junk) pointers.
Why Time Exceeded. Because with critical error program can hang up and/or crash. Meaning it also doesn't deliver result in time.
So I think you have to debug your program to find all coding errors, not spending your time optimizing algorithm.
Regarding this line s.erase(i-k, k); - it may crash/hang-up when i < k, then you have negative value, which is not allowed by .erase() method. When you get for example i - k equal to -1 then size_t type (type of first argument of erase) will overflow (wrap around) to value 18446744073709551615 which is defnitely out of bounds, and out of memory border, hence your program may crash and/or hang. Also erase crashes when there is too many chars deleted, i.e. for erase s.erase(a, b) you have to watch that a + b <= s.size(), it is not controlled by erase function.
See documentation of erase method, and don't put negative values as arguments to this method. Check that your algorithm never has negative value i.e. never i < k when calling s.erase(i-k, k);, also never i-k + k > s.size(). To make sure there is no program crash you may do following:
int start = std::min(std::max(0, i-k), int(s.size()));
int num = std::min(k, std::max(0, int(s.size()) - start));
s.erase(start, num);

Why does only one of my return tuple work but is fine when I print it out?

I'm having trouble understanding why my return data is garbage when I don't use debug to print it out and is fine when I do print it out. I am using C++ make_tuple and tie on the other end for float values. If I don't include enough info let me know!
I have tried checking for uninitialized data by printing out my functions. I also use this exact same code in other parts of the program with no issue.
To give a background of what this program is. I am reading an adc value getting the max value (with error checking) and then sending it for a pass-fail for the system and display to the user. I can work around this in a few ways but I am mostly just curious about this bug.
std::tuple<float,float> hardware_control::hv_check()
{
float hv_filtered_max = 0;
float hv_filtered_avg = 0;
int samples = HV_SAMPLES;
float hv_adc_read[samples];
int non_zero_samples = 0;
int i = 0;
int loops = 0;
//here we will take the a number of samples, average and find the max
while((i < samples) && (hv_filtered_max < HV_Voltage_MAX_CHECK)) // check if less than HV_MIN to speed up test (basically stop testing if it has passed the check)
{
hv_adc_read[i] = check_adc(7);
if(hv_adc_read[i] > 0 && hv_adc_read[i] < 10)
{
hv_filtered_avg += hv_adc_read[i];
non_zero_samples++;
i++;
}
if((hv_adc_read[i] > hv_filtered_max) && hv_adc_read[i] < 10)
{
hv_filtered_max = hv_adc_read[i];
}
loops++;
if(loops > 500) // stop sampling at 500 if we never get anything (this is protection for it possibly freezing i we sample nothing)
{
hv_filtered_max = 0;
break;
}
}
hv_filtered_avg = hv_filtered_avg/non_zero_samples;
return std::make_tuple(hv_filtered_avg,hv_filtered_max);
}
hardware_control hwc;
//where I call and return the data
std::tie(Ins_Data.hv_avg,Ins_Data.hv_max) = hwc.hv_check();
//Me printing out the values
qDebug()<<"MAX_OUTSIDE"<<Ins_Data.hv_max<<endl;
Ins_Data.hv_errors = hwc.HV_error_check();
log_data.push_back("HV_AVG");
log_data.push_back(QString::number(Ins_Data.hv_avg*3));
log_data.push_back("HV_MAX");
log_data.push_back(QString::number(Ins_Data.hv_max*3));
Why this annoys me so bad is that every time I print it out with the qDebug() function it works! if I comment it out, it goes back to 3.8581*10^-38
The value magically comes back to the correct value.
What's going on here? My guess is the make_tuple and tie is corrupting the memory but if so then why is it only sporadically doing it? and why only one of the floats?
SOLVED
I was sampling beyond my initialized array. My array is set to "HV_SAMPLES" however the max number of loops was 500, therefore it sampled beyond the size of my array. Debug functionality must have added some cushion between the array and other values allowing it to output correctly.

Fibonacci Sequence with vectors

I'm currently trying to solve some problems of the Euler-Projects, but I'm currently stuck at the second problem. Here is what I have right now:
void p002()
{
unsigned int result = 0;
std::vector<int> fibonacci{ 1,2 };
for (int i = 2; fibonacci.at(i) < 4000000; i++)
{
fibonacci.at(i) = fibonacci.at(i - 1) + fibonacci.at(i - 2); //<- Doesn't work
if (fibonacci.at(i) % 2 == 0)
result += fibonacci.at(i);
}
std::cout << result;
}
Could someone help me out and tell me why this one line doesn't seem to work? (I get an "abort() called" error when trying to execute the code.)
In case anyone wonders: The task is to get the sum of all integers of the fibonacci sequence with a lower value than 4,000,000 which are even-valued.
Thanks!
vector::at throws an exception if you try to access an element at an index that is out of bounds. Your vector contains 2 elements (at indices 0 and 1). Therefore fibonacci.at(2) is out of bounds, and an exception is thrown. You don't catch the exception, so std::terminate is called. By default, std::terminate points to abort which terminates your process.
Solution: Add enough elements into the vector so that fibonacci.at(i) isn't out of bounds.

How do I fix this runtime error related to div by zero?

Here is the chunk of code in question that I've pulled from my program:
#include <vector>
using namespace std;
vector<double> permittingConstructionCosts(56);
static const int PERMITTING_PERIODS = 0;
static const int CONSTRUCTION_PERIODS = 11;
static const double CONSTRUCTION_COSTS = 2169506;
static const double PERMITTING_COSTS = 142085;
static const int PERMITTING_CONSTRUCTION_PERIODS = PERMITTING_PERIODS + CONSTRUCTION_PERIODS;
void calcExpenses // Calculates permitting and construction expenses
(
vector<double>& expense,
double value1,
double value2
)
{
int i;
for (i=0; i<=PERMITTING_PERIODS + 1; i++)
{
expense[i] = value1;
}
for (i=PERMITTING_PERIODS + 2; i<expense.size(); i++)
{
if (i < PERMITTING_CONSTRUCTION_PERIODS + 2)
{
expense[i] = value2;
}
}
}
int main()
{
if (PERMITTING_PERIODS != 0)
{
calcExpenses(permittingConstructionCosts, -PERMITTING_COSTS/PERMITTING_PERIODS, -CONSTRUCTION_COSTS/CONSTRUCTION_PERIODS);
}
else
{
calcExpenses(permittingConstructionCosts, 0, -CONSTRUCTION_COSTS/CONSTRUCTION_PERIODS);
}
return 0;
}
According to ideone (http://ideone.com/LpzUny) the code has a runtime error that returns "time: 0 memory: 3456 signal:11".
I've tried to look for solutions on SO and found the following links:
How can I avoid a warning about division-by-zero in this template code?
How to eliminate "divide by 0" error in template code
However, I don't know how to use templates because I am new to c++ and I'm not sure I need to use them in this case so I have no clue how to adapt those solutions to my particular problem if it's even possible.
I'm pretty sure that the "-PERMITTING_COSTS/PERMITTING_PERIODS" is causing the problem but I thought that simply checking the divisor would solve the problem. This function seems to work for every other value other than 0 but I need to account for the case where PERMITTING_PERIODS = 0 somehow.
I would very much appreciate any help I can get. Thanks in advance!
Edit: I actually do initialize the vector in my program but I forgot to put that in because the size is decided elsewhere in the program. The chunk of code works once I fix that part by putting in a number but my program still has a runtime error when I set PERMITTING_PERIODS to 0 so I guess I have to go bug hunting elsewhere. Thanks for the help!
The problem lies inside the function, which is called by the else statement in the main function:
for (i=0; i<=PERMITTING_PERIODS + 1; i++)
{
expense[i] = value1;
}
Here, PERMITTING_PERIODS is 0, thus you loop from 0 to 2 (inclusive).
However, expense.size() is 0, since your vector is empty. As a result, you are trying to access an empty vector, which causes a segmentation fault.
With that said, print the value of i inside the loop, you should see that you try to access expense[0], but the vector is empty, so it has no first slot (basically it doesn't have any)!!
So replace that with:
expense.push_back(value1);
which will allocate enough space for your values to be pushed into the vector.
The answer given in the cited links, (i.e. "How to eliminate "divide by 0" error in template code") applies equally well here. The other answers were given in the context of templates, but this is completely irrelevant. The sample principle applies equally well with non-template code, too. The key principle is to compute a division, but if the denominator is zero, you want to compute the value of zero instead of the division.
So we want to compute -PERMITTING_COSTS/PERMITTING_PERIODS, but use the value of 0 instead of the division when PERMITTING_PERIODS is 0. Fine:
int main()
{
calcExpenses(permittingConstructionCosts,
(PERMITTING_PERIODS == 0 ? 0: -PERMITTING_COSTS)/
(PERMITTING_PERIODS == 0 ? 1: PERMITTING_PERIODS),
-CONSTRUCTION_COSTS/CONSTRUCTION_PERIODS);
return 0;
}