Я работаю над программой, которая считывает информацию из текстового файла, а затем вычисляет среднее значение, медиану, режим, диапазон, стандартное отклонение и его дисперсию. Как я могу отсортировать числа из входного файла в порядке возрастания и найти медиану и диапазон этих значений? Все числа во входном файле .txt расположены в случайном порядке.

#include <iostream>
#include <cmath>
#include <string>
#include <fstream>
#include <iomanip>
#include <sstream>



using namespace std;

int main()
{

// Define Variables
    string null;
    int input=0, counter=0, numAscend=0;
    float datSum, datMean;
    const string SPCHAR= " ";

// File Algorithms
    // Input File and Output File
        ifstream fin; // <--- Reading from this File
        ofstream myfile; // <--- Writing to this File

    // Output File Computing
        // Place the directory to the file you want to write to here.
myfile.open("/home/anomaly/Desktop/finaldata.txt");

        // What is being wrote to the output file.
myfile << "Writing this to a file.\n";


fin.open("/home/anomaly/Desktop/arsenic.txt");


// Main Operation of Program

        fin >> input;
    getline(fin, null);
    while (fin.good())
    {
        datSum += input;
        fin >> input;
        getline(fin, null);
        counter++;
    }

    // Data Configurations
        datMean = (datSum / counter);






    cout << "There are " << counter << " item(s)" << endl;
    cout << setprecision(1) << input << endl;
    cout << fixed << setprecision(2) << SPCHAR << "The mean is " << datMean << SPCHAR << SPCHAR << SPCHAR << SPCHAR << SPCHAR << SPCHAR << " The variance is " << endl;
    cout << fixed << setprecision(2) << SPCHAR << SPCHAR << "The median is " << datSum << SPCHAR << SPCHAR << SPCHAR << " The Stand. Deviation is " << endl;
    cout << fixed << setprecision(2) << SPCHAR << SPCHAR << SPCHAR << "The mode is " << datSum << SPCHAR << SPCHAR << SPCHAR << SPCHAR << SPCHAR << SPCHAR << " The range is " << endl;






    myfile << setprecision(2) << datSum << endl;


return 0;
}
c++
0
Adam 5 Ноя 2019 в 16:26
Однако std::set не поможет вам с медианой. Таким образом, вам придется сохранить полную коллекцию, включая дубликаты. Может быть, в std::multiset?
 – 
eike
5 Ноя 2019 в 16:40
Зачем использовать std::set? первое, что приходит мне на ум, это std::sort
 – 
apple apple
5 Ноя 2019 в 16:41
3
В основном 1. прочитать все значения в std::vector 2. std::sort std::vector (или любой другой метод сортировки) 3. теперь у вас есть отсортированный набор данных, делайте все, что хотите.
 – 
apple apple
5 Ноя 2019 в 16:44
Правда... неаккуратное чтение с моей стороны.
 – 
Ted Lyngmo
5 Ноя 2019 в 17:08
Связано: boost::accumulator_set
 – 
Caleth
6 Ноя 2019 в 18:40

1 ответ

Я предлагаю вам прочитать все значения из файла и поместить их в std::vector, чтобы упростить вычисления.

Это один из способов сделать это с некоторыми примерами того, как сортировать, суммировать и вычислять средние и медианные значения.

#include <algorithm> // std::sort
#include <fstream>
#include <iostream>
#include <iterator>  // std::istream_iterator, std::back_inserter
#include <numeric>   // std::accumulate
#include <string>
#include <vector>    // std::vector

// a function to read all values of a certain type (T) from a stream
// and put them in a vector
template<typename T>
std::vector<T> extract_data_from_stream(std::istream& is) {
    std::vector<T> retval;

    // copy all values from the stream and put them in a vector
    std::copy(std::istream_iterator<T>(is), std::istream_iterator<T>(),
              std::back_inserter(retval));

    // not at end-of-file, extraction ran into problems 
    if(is.eof() == false)
        throw std::runtime_error("extraction failed");

    return retval;
}

// a wrapper function to open a file and call the above function
template<typename T>
std::vector<T> extract_data_from_file(const std::string& filename) {
    // open the file
    std::ifstream fin(filename);

    // if the file was opened ok, extract all data and return it
    if(fin) return extract_data_from_stream<T>(fin);

    // else throw
    throw std::runtime_error("Could not open " + filename + " for reading");
}

int main() {
    try {
        // get all int:s from a file as a std::vector<int>
        auto data = extract_data_from_file<int>("/home/anomaly/Desktop/arsenic.txt");

        // sort the data
        std::sort(data.begin(), data.end());

        // print the data
        std::copy(data.begin(), data.end(),
                  std::ostream_iterator<int>(std::cout, " "));
        std::cout << "\n";

        // sum of the data
        int datSum = std::accumulate(data.begin(), data.end(), 0);

        std::cout << "number of values: " << data.size() << "\n";
        std::cout << "sum:              " << datSum << "\n";

        if(data.size()) { // mean and median must have data
            // get the mean value
            float datMean =
                static_cast<float>(datSum) / static_cast<float>(data.size());

            // find/calculate the median value
            float datMedian;
            size_t mid = data.size() / 2;

            if(data.size() % 2) // odd number of values
                datMedian = static_cast<float>(data[mid]);
            else                // even number of values
                datMedian = static_cast<float>(data[mid - 1] + data[mid]) / 2.f;

            std::cout << "mean:             " << datMean << "\n";
            std::cout << "median:           " << datMedian << "\n";
        }
    } catch(const std::exception& ex) {
        std::cerr << ex.what() << "\n";
    }
}
2
Ted Lyngmo 6 Ноя 2019 в 18:50
Вы, вероятно, захотите настроить поток так, чтобы он выдавал исключение при ошибке или сбое, иначе нет другого способа узнать, не удалось ли прочитать.
 – 
Toby Speight
6 Ноя 2019 в 18:31
Или template<typename T> std::vector<T> extract_data_from_stream(std::istream& is) { return { std::istream_iterator<T>(is), std::istream_iterator<T>() }; }
 – 
Caleth
6 Ноя 2019 в 18:38
1
Я согласен, что это было бы неплохо, но установка failbit в маске исключения заставляет каждый раз выбрасывать std::copy. Вместо этого добавлен дешевый чек.
 – 
Ted Lyngmo
6 Ноя 2019 в 18:52
Действительно, но с добавленной проверкой, что извлечение прошло успешно, это уже не сработает. Если бы я мог найти маску исключения, которая позволила бы std::copy выполнять работу без исключения, когда все значения действительны, я бы согласился на ваше предложение.
 – 
Ted Lyngmo
6 Ноя 2019 в 18:53