2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 OMP , разные значения сумм.
Сообщение05.04.2025, 03:18 
Задача такая: Определить класс CIntN для работы с целыми знаковыми числами, состоящими lо N десятичных цифр, где N задается в конструкторе.
В классе должны быть определены необходимые конструкторы, деструктор, операторы присваивания, сложения, вычитания.
Написать функцию и конструктор сохранения переменной данного типа в файл и загрузки из файла. В отдельном файле должен быть написан тест на данный класс.

В процессе сдачи преподаватель попросил переписать тип данных на входе из char в String. Но почему-то теперь неверные значения сумм выходят. Никак не получается найти ошибку. Помогите, пожалуйста, советом


func.cpp
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <string>
#include "func.h"
using namespace std;
vector<CIntN*> input(string sf)
{
        vector<CIntN*> nums;
        ifstream fin(sf);
        string str;
        if (fin.is_open())
        {
            string str;
                for (; getline(fin, str);)
                {

                        char type = str[0];
                        string number=str.substr(2);
                        if (type=='0')
                        {
                                CIntN* num = new CIntN0(number);
                                nums.push_back(num);
                                //delete num;
                        }
                        else
                        {
                                CIntN* num = new CIntN1(number);
                                nums.push_back(num);
                                //delete num;
                        }
                }
                fin.close();
        }
        return nums;
}
CIntN0 sum(vector<CIntN*> t)
{
        const int n = t.size();
        CIntN0 res("0");
        for (int i = 0; i < n; i++)
        {
            res += *t[i];
        }
        return res;
}
CIntN0 sumOmp(vector<CIntN*> t)
{
        const int n = t.size();
        CIntN0 res("0");
#pragma omp declare reduction(+:CIntN:omp_out=omp_out+omp_in)//initializer(omp_priv=omp_orig)
#pragma omp parallel for reduction(+:res)
        for (int i = 0; i < n; i++)
        {
            res = res + *t[i];
        }
        return res;
}
void CIntGen(const int n, int max)
{
        ofstream fout("input.txt");
        for (int i = 0; i < n; i++)
        {
                fout << rand() % 2 << ' ' << rand() % max << '\n';
        }
        fout << 0 << ' ' << 0 << '\0';
        fout.close();
}
void output(vector<CIntN*> t)
{
        for (auto it=t.begin();it!=t.end();++it)
        {
                CIntN* td = *it;
                td->output();
        }
}
 


CIntN.cpp
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include "CIntN.h"
CIntN::CIntN(string number)
{
        setZero();
        if (number.length())
        {
                int j = 0;
                if (number[0] == '-')
                {
                        sign = '-';
                        num = new int[this->n = number.length() - 1];
                        for (int i = n; i > 0; i--) { num[j] = (int)number[i] - 48; j++; }
                }
                else
                {
                        sign = '+';
                        num = new int[this->n = number.length()];
                        for (int i = n - 1; i > -1; i--) { num[j] = (int)number[i] - 48; j++; }
                }
        }
}
CIntN CIntN::operator+(const CIntN& b)
{
        int N;
        if (n >= b.n) N = n + 1;
        else N = b.n + 1;
        CIntN x = N; x.sign = sign;
        for (int i = 0; i < n; i++)     x.num[i] = num[i];
        for (int i = n; i < N; i++) x.num[i] = 0;
        CIntN y = N; y.sign = b.sign;
        for (int i = 0; i < b.n; i++) y.num[i] = b.num[i];
        for (int i = b.n; i < N; i++) y.num[i] = 0;
        CIntN res = N;
        if (x.sign == y.sign)
        {
                res.sign = x.sign;
                for (int i = 0; i < N; i++)
                {
                        if (x.num[i] + y.num[i] > 9)
                        {
                                for (int j = i + 1; j < N; j++) if (x.num[j] != 9) { x.num[i + 1]++; break; }
                        }
                        res.num[i] = (x.num[i] + y.num[i]) % 10;
                }
        }
        else
        {
                if (x.sign == '+') { y.sign = '+'; return x - y; }
                else { x.sign = '+'; return y - x; }
        }
        for (int i = N - 1; i > -1; i--)
        {
                if (res.num[i] == 0) N--;
                else break;
        }
        CIntN c = N; c.sign = res.sign;
        for (int i = 0; i < N; i++) c.num[i] = res.num[i];
        return c;
}
CIntN CIntN::operator-(const CIntN& b)
{
        int N;
        if (n >= b.n) N = n;
        else N = b.n;
        CIntN x = N; x.sign = sign;
        for (int i = 0; i < n; i++)     x.num[i] = num[i];
        for (int i = n; i < N; i++) x.num[i] = 0;
        CIntN y = N; y.sign = b.sign;
        for (int i = 0; i < b.n; i++) y.num[i] = b.num[i];
        for (int i = b.n; i < N; i++) y.num[i] = 0;
        CIntN res = N;
        if (x.sign == y.sign)
        {
                if (x > y)
                {
                        res.sign = x.sign;
                        for (int i = 0; i < N; i++)
                        {
                                if (x.num[i] - y.num[i] < 0)
                                {
                                        int j = i + 1;
                                        while (x.num[j] == 0 && j < N) { x.num[j] = 9; j++; }
                                        if (j < N)
                                        {
                                                x.num[j]--;
                                                res.num[i] = x.num[i] + 10 - y.num[i];
                                        }
                                        else { for (j = 0; j < N; j++) { res.num[j] = 0; } break; }
                                }
                                else res.num[i] = x.num[i] - y.num[i];
                        }
                }
                else if (x < y)
                {
                        res.sign = '-';
                        for (int i = 0; i < N; i++)
                        {
                                if (y.num[i] - x.num[i] < 0)
                                {
                                        int j = i + 1;
                                        while (y.num[j] == 0 && j < N) { y.num[j] = 9; j++; }
                                        if (j < N)
                                        {
                                                y.num[j]--;
                                                res.num[i] = y.num[i] + 10 - x.num[i];
                                        }
                                        else { for (j = 0; j < N; j++) { res.num[j] = 0; } break; }
                                }
                                else res.num[i] = y.num[i] - x.num[i];
                        }
                }
                else
                {
                        CIntN c = 1;
                        c.num[0] = 0;
                        return c;
                }
        }
        else
        {
                if (x.sign == '+') { y.sign = '+'; return x + y; }
                else { y.sign = '-'; return x + y; }
        }
        for (int i = N - 1; i > -1; i--)
        {
                if (res.num[i] == 0) N--;
                else break;
        }
        CIntN c = N; c.sign = res.sign;
        for (int i = 0; i < N; i++) c.num[i] = res.num[i];
        return c;
}
CIntN CIntN::operator+=(const CIntN& b)
{
        int N;
        if (n >= b.n) N = n + 1;
        else N = b.n + 1;
        CIntN x = N; x.sign = sign;
        for (int i = 0; i < n; i++) x.num[i] = num[i];
        for (int i = n; i < N; i++) x.num[i] = 0;
        CIntN y = N; y.sign = b.sign;
        for (int i = 0; i < b.n; i++) y.num[i] = b.num[i];
        for (int i = b.n; i < N; i++) y.num[i] = 0;
        CIntN res = N;
        if (x.sign == y.sign)
        {
                res.sign = x.sign;
                for (int i = 0; i < N; i++)
                {
                        if (x.num[i] + y.num[i] > 9)
                        {
                                for (int j = i + 1; j < N; j++) if (x.num[j] != 9) { x.num[i + 1]++; break; }
                        }
                        res.num[i] = (x.num[i] + y.num[i]) % 10;
                }
        }
        else
        {
                if (x.sign == '+') { y.sign = '+'; return x - y; }
                else { x.sign = '+'; return y - x; }
        }
        for (int i = N - 1; i > -1; i--)
        {
                if (res.num[i] == 0) N--;
                else break;
        }
        CIntN c = N; c.sign = res.sign;
        for (int i = 0; i < N; i++) c.num[i] = res.num[i];
        *this=c;
        return *this;
}
bool CIntN::operator>(const CIntN& b)
{
        if (n == b.n)
        {
                for (int i = n - 1; i > -1; i--) if (num[i] != b.num[i]) return num[i] > b.num[i];
        }
        else return n > b.n;
        return false;
}
bool CIntN::operator<(const CIntN& b)
{
        if (n == b.n)
        {
                for (int i = n - 1; i > -1; i--) if (num[i] != b.num[i]) return num[i] < b.num[i];
        }
        else return n < b.n;
        return false;
}
string CIntN::makeStr()
{
        string num = "";
        if (sign == '-') num += '-';
        for (int i = n - 1; i > -1; i--) num += (this->num[i] + 48);
        return num;
}
void CIntN::output()
{
        if (sign == '-') cout << sign;
        for (int i = n - 1; i > -1; i--) cout << num[i];
        cout << endl;
}
void CIntN::print()
{
        if (sign == '-') cout << sign;
        for (int i = n - 1; i > -1; i--) cout << num[i];
        cout << endl;
}


CIntN.h
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#pragma once
#include <iostream>
#include <fstream>
#include <istream>
#include <string.h>
using namespace std;
class CIntN
{
private:
        int* num; int n; char sign;
public:
        //---
        CIntN() { setZero(); }
        CIntN(int n) { setZero(); if (n) num = new int[this->n = n]; sign = '+'; }
        CIntN(const CIntN& b) { copyOnly(b); }
        CIntN(CIntN&& b) { n = b.n; num = b.num; sign = b.sign; b.setZero(); }
        CIntN(string number);
        CIntN& operator=(const CIntN& b) { if (&b != this) { clean(); copyOnly(b); } return *this; }
        CIntN& operator=(CIntN&& b) { if (&b != this) { clean(); n = b.n; sign = b.sign; num = b.num; b.setZero(); } return *this; }
        virtual ~CIntN() { clean(); }
        //---
        void setZero() { num = nullptr; n = 0; sign = ' '; }
        void clean() { delete[] num; setZero(); }
        void copyOnly(const CIntN& b) { setZero(); if (b.size()) { memcpy(num = new int[n = b.n], b.num, b.n * sizeof(*num)); } sign = b.sign; }
        //---
        string makeStr();
        virtual void output();
        void print();
        //---
        size_t size() const { return n; }
        CIntN operator+(const CIntN& b);
        CIntN operator-(const CIntN& b);
        CIntN operator+=(const CIntN& b);
        bool operator>(const CIntN& b);
        bool operator<(const CIntN& b);
};



CIntN0.cpp
Используется синтаксис C++
#include "CIntN0.h"
void CIntN0::output()
{
        ofstream fout("output0.txt",ios::app);
        fout << makeStr() << endl;
        fout.close();
}



CIntN0.h
Используется синтаксис C++
#pragma once
#include "CIntN.h"
class CIntN0 :
    public CIntN
{
public:
    CIntN0() :CIntN() {}
    CIntN0(int n) : CIntN(n) {}
    CIntN0(const CIntN& b) : CIntN(b) {}
    CIntN0(CIntN&& b) : CIntN(b) {}
    CIntN0(string number) :CIntN(number) {}
    void output();
};
 



CIntN1.cpp
Используется синтаксис C++
#include "CIntN1.h"
void CIntN1::output()
{
        ofstream fout("output1.txt",ios::app);
        fout << makeStr() << ' ';
        fout.close();
}


CIntN1.h
Используется синтаксис C++
[#pragma once
#include "CIntN.h"
class CIntN1 :
    public CIntN
{
public:
    CIntN1() :CIntN() {}
    CIntN1(int n) : CIntN(n) {}
    CIntN1(const CIntN& b) : CIntN(b) {}
    CIntN1(CIntN&& b) : CIntN(b) {}
    CIntN1(string number) :CIntN(number) {}
    void output();
};
 


func.h
Используется синтаксис C++
#pragma once
#include <vector>
#include <omp.h>
#include <time.h>
#include "CIntN0.h"
#include "CIntN1.h"
vector<CIntN*> input(string sf);
CIntN0 sum(vector<CIntN*> t);
CIntN0 sumOmp(vector<CIntN*> t);
void CIntGen(const int n, int max);
void CIntGenOmp(const int n, int max);
void output(vector<CIntN*> t);


main.cpp
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include "func.h"
int main(void)
{
    srand(time(NULL));
        time_t t1, t2, dt1;
        CIntGen(100000000, 1000000);
        vector<CIntN*> tn = input("input.txt");
        t1 = clock();
        sum(tn).print();
        t2 = clock();
        dt1 = (t2 - t1);
        cout << "Without OMP: " << dt1 << endl;
        for(auto &p:tn)
        {
            delete p;
            p=nullptr;
        }
        tn = input("input.txt");
        t1 = clock();
        sumOmp(tn).print();
        t2 = clock();
        dt1 = (t2 - t1);
        cout << "With OMP: " << dt1 << endl;
        for(auto &p:tn)
        {
            delete p; p=nullptr;
        }

        return 0;
}

 
 
 
 Re: OMP , разные значения сумм.
Сообщение14.04.2025, 17:56 
Аватара пользователя
А в чем назначение вот этого ветвления при чтении чисел

Код:
                        char type = str[0];
                        string number=str.substr(2);
                        if (type=='0')


Что это за "типы" чисел и где все это описано в условии задачи?

 
 
 [ Сообщений: 2 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group