I've written a program where the user can enter any number of values into a vector and it's supposed to return the quartiles, but I keep getting a "vector subscript out of range" error :
#include "stdafx.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <ios>
#include <vector>
int main () {
using namespace std;
cout << "Enter a list of numbers: ";
vector<double> quantile;
double x;
//invariant: homework contains all the homework grades so far
while (cin >> x)
quantile.push_back(x);
//check that the student entered some homework grades
//typedef vector<double>::size_type vec_sz;
int size = quantile.size();
if (size == 0) {
cout << endl << "You must enter your numbers . "
"Please try again." << endl;
return 1;
}
sort(quantile.begin(), quantile.end());
int mid = size/2;
double median;
median = size % 2 == 0 ? (quantile[mid] + quantile[mid-1])/2 : quantile[mid];
vector<double> first;
vector<double> third;
for (int i = 0; i!=mid; ++i)
{
first[i] = quantile[i];
}
for (int i = mid; i!= size; ++i)
{
third[i] = quantile[i];
}
double fst;
double trd;
int side_length = 0;
if (size % 2 == 0)
{
side_length = size/2;
}
else {
side_length = (size-1)/2;
}
fst = (size/2) % 2 == 0 ? (first[side_length/2]/2 + first[(side_length-1)/2])/2 : first[side_length/2];
trd = (size/2) % 2 == 0 ? (third[side_length/2]/2 + third[(side_length-1)/2])/2 : third[side_length/2];
streamsize prec = cout.precision();
cout << "The quartiles are" << setprecision(3) << "1st"
<< fst << "2nd" << median << "3rd" << trd << setprecision(prec) << endl;
return 0;
}
First Quartile(Q1)=((n+1)/4)th Term also known as the lower quartile. The second quartile or the 50th percentile or the Median is given as: Second Quartile(Q2)=((n+1)/2)th Term. The third Quartile of the 75th Percentile (Q3) is given as: Third Quartile(Q3)=(3(n+1)/4)th Term also known as the upper quartile.
Quartile Formula: There are four different formulas to find quartiles: Formula for Lower quartile (Q1) = N + 1 multiplied by (1) divided by (4) Formula for Middle quartile (Q2) = N + 1 multiplied by (2) divided by (4) Formula for Upper quartile (Q3) = N + 1 multiplied by (3) divided by (4)
Instead of doing std::sort(quantile.begin(), quantile.end())
a somewhat cheaper way would be
auto const Q1 = quantile.size() / 4;
auto const Q2 = quantile.size() / 2;
auto const Q3 = Q1 + Q2;
std::nth_element(quantile.begin(), quantile.begin() + Q1, quantile.end());
std::nth_element(quantile.begin() + Q1 + 1, quantile.begin() + Q2, quantile.end());
std::nth_element(quantile.begin() + Q2 + 1, quantile.begin() + Q3, quantile.end());
This would not sort the complete array, but only do a "between groups" sort of the 4 quartile. This saves on the "within groups" sort that a full std::sort
would do.
If your quantile
array is not large, it's a small optimization. But the scaling behavior of std::nth_element
is O(N)
however, rather than O(N log N)
of a std::sort
.
This C++ template function calculates quartile for you. It assumes x
to be sorted.
#include <assert.h>
template <typename T1, typename T2> typename T1::value_type quant(const T1 &x, T2 q)
{
assert(q >= 0.0 && q <= 1.0);
const auto n = x.size();
const auto id = (n - 1) * q;
const auto lo = floor(id);
const auto hi = ceil(id);
const auto qs = x[lo];
const auto h = (id - lo);
return (1.0 - h) * qs + h * x[hi];
}
To use it do:
std::vector<float> x{1,1,2,2,3,4,5,6};
std::cout << quant(x, 0.25) << std::endl;
std::cout << quant(x, 0.50) << std::endl;
std::cout << quant(x, 0.75) << std::endl;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With