12

ユーザーがベクトルに任意の数の値を入力でき、四分位数を返すことになっているプログラムを作成しましたが、「ベクトル添え字が範囲外です」というエラーが発生し続けます。

#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;   

}
4

7 に答える 7

26

std::sort(quantile.begin(), quantile.end())やや安価な方法を行う代わりに、

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());

これは完全な配列をソートするのではなく、4 四分位数の「グループ間」ソートのみを行います。これにより、完全に実行される「グループ内」ソートが節約されstd::sortます。

配列が大きくない場合quantile、それは小さな最適化です。ただし、 のスケーリング動作はstd::nth_elementではO(N)なくO(N log N)ですstd::sort

于 2012-08-15T07:13:45.607 に答える
11

これは、MATLAB の線形補間に相当する分位関数です。

#include <algorithm>
#include <cmath>
#include <vector>

template<typename T>
static inline double Lerp(T v0, T v1, T t)
{
    return (1 - t)*v0 + t*v1;
}

template<typename T>
static inline std::vector<T> Quantile(const std::vector<T>& inData, const std::vector<T>& probs)
{
    if (inData.empty())
    {
        return std::vector<T>();
    }

    if (1 == inData.size())
    {
        return std::vector<T>(1, inData[0]);
    }

    std::vector<T> data = inData;
    std::sort(data.begin(), data.end());
    std::vector<T> quantiles;

    for (size_t i = 0; i < probs.size(); ++i)
    {
        T poi = Lerp<T>(-0.5, data.size() - 0.5, probs[i]);

        size_t left = std::max(int64_t(std::floor(poi)), int64_t(0));
        size_t right = std::min(int64_t(std::ceil(poi)), int64_t(data.size() - 1));

        T datLeft = data.at(left);
        T datRight = data.at(right);

        T quantile = Lerp<T>(datLeft, datRight, poi - left);

        quantiles.push_back(quantile);
    }

    return quantiles;
}

四分位数を求める:

std::vector<double> in = { 1,2,3,4,5,6,7,8,9,10,11 };
auto quartiles = Quantile<double>(in, { 0.25, 0.5, 0.75 });
于 2016-06-08T17:13:08.187 に答える
2

コンテンツを設定する前に、事前に割り当ててベクトル化する必要がありfirstますthird

vector<double> first(mid);
vector<double> third(size-mid);

またはpush_backへの代入の代わりにfirst[i]使用third[i]

于 2012-08-15T06:17:28.353 に答える
0

ここに 1 つのエラーがあります。

vector<double> first;
vector<double> third;

for (int i = 0; i!=mid; ++i)
{
    first[i] = quantile[i];
}

ベクターfirstにはコンテンツがありませんが、コンテンツにアクセスしようとしています。thirdとそのループと同じ問題。push_back代わりに使うということですか?

于 2012-08-15T05:44:07.333 に答える
0

ベクトルの要素が 1 つだけの場合、この命令は範囲外です。

quantile[mid-1]

「i」は途中からなので、3番目[0]は範囲外です

for (int i = mid; i!= size; ++i)
{
    third[i] = quantile[i];
}
于 2012-08-15T05:38:49.207 に答える