在C ++中将int数据类型和自定义类数据类型相加以获得更高的性能

问题描述

我产生了自己的类long_number,以进行比long long int更高的数字数学运算(用于质数等)。现在,我正在测试加法并比较以下代码的速度:

#include <iostream>
#include <cmath>
#include <vector>
#include <typeinfo>
#include <string>
//#include "long_number.h" the header is below
#include <chrono>

using namespace std;
using namespace ln;

typedef long long int Te;
typedef long_number Se;

int main()
{

    // Start measuring time
    
    vector<Te> numbers;
    string s = "";
    for(int i=1;i<15;i++)
    {
        s.append(to_string(i));
        numbers.push_back(stoll(s));
    }
    auto begin = std::chrono::high_resolution_clock::Now();
    Te sum=0; 
    for(int k=0;k<=5000;k++)
    {
        sum=0;
    for(int j=1;j<=7;j++)
    for(int i =0;i<numbers.size();i++)
        sum +=numbers[i];
    }
    cout << "Sum " <<sum <<endl;
    auto end = std::chrono::high_resolution_clock::Now();
    auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
    printf("Time measured: %.6f seconds.\n",elapsed.count() * 1e-9);

    vector<Se> numbers2;
    string se;
    for(int i=1;i<15;i++)
    {
        se.append(to_string(i));
        numbers2.push_back((Se)stoll(se));
    }
    begin = std::chrono::high_resolution_clock::Now();
    Se sum2=0;
    for(int k=0;k<=5000;k++)
    {
        sum2=0;
    for(int j=1;j<=7;j++)
    for(int i =0;i<numbers2.size();i++)
        sum2 += numbers2[i];
    }
    cout << "Sum " <<sum2 <<endl;
    end = std::chrono::high_resolution_clock::Now();
    elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
     printf("Time measured: %.6f seconds.\n",elapsed.count() * 1e-9);
    return 0;
}

使用g ++ main.cpp -Wall -O3 -std = c ++ 17 -o程序编译的结果显示以下结果:

Sum 8729267916327544355
Time measured: 0.000474 seconds.
Sum 8729267916327544355
Time measured: 0.677444 seconds.

您可以看到,int加法快了大约1000倍。我的课程long_number如下:

#include <iostream>
#include <cmath>
#include <vector>
#include <typeinfo>
#include <string>


using namespace std; 

namespace ln
{
//stores long integers in vector,0th position means 10^0 -> reversed order,using for operation of huge nubers overnight 
class long_number
{
private:

public:
vector<unsigned int> numero = {};//every component store one digit of the number
unsigned int size = 0;//size of the numero - how many digit has the number

long_number() {};//default constructor


void zero_check()//checks and remuves zero digits from the left of the number
{
    while(numero[numero.size()-1]==0&&numero.size()>=2)
    {
        numero.pop_back();
        size--;
    }
    size = numero.size();
}


operator unsigned int() const //conversion form long_number to int
{  
    //cout << "typecast operator unsigned int() used" << endl;
    unsigned int num=0;
    for(unsigned int i=0;i<size;i++)
        num += numero[i]*pow(10.,i);
    return num;
}       


template<typename numb>
long_number(numb a)//constructor
{
    string b = to_string(a);
    read(b);
}

long_number(const long_number& a)//copy constructor
{
    numero = a.numero;
    size = a.numero.size();
}

int ssize() const
{
    return (this->numero).size();
}


void set_size(int i)
{
    (this->numero).resize(i);
}
void get (ostream& out) const;//historic function to print the long_number
void read(string input); //historic function to declare long_number
vector <unsigned int> get_numero() const //not necessary cauz all is public
{
    return numero;
}
void set_numero(int num,int pos)
{
numero[pos]=num;
}





long_number& operator+=(const long_number& b)//defined by the binary operator +
{
    long_number a= *this;
    *this = (a + b);
    return *this;
}



template <typename numb>
long_number& operator=( numb b)// I don't kNow why is this here
{
    string s = to_string(b);
    this->read(s);
    return *this;

}


~long_number(){}//destructor

//this is here to get acces inside the operators to another operators
//it should work also without this according to
//https://www.learncpp.com/cpp-tutorial/9-2a-overloading-operators-using-normal-functions/
//because all is public but it doesnt
friend long_number operator + ( const long_number&,const  long_number&);

};

long_number operator+ (const long_number& a,const long_number& b)//sum of two long_numbers
{   
    long_number res;
    int ten = 10;
    int a_size=a.get_numero().size();//size of number a
    int b_size=b.get_numero().size();//size of number b
    res.set_size(max(a_size,b_size)+1);
    int rest = 0; //stores the rest when adding over ten
    for(int i=0;i<min(a_size,b_size);i++)//part where both numbers have digits
    {
        res.set_numero((a.get_numero()[i]+(b.get_numero())[i]+rest)%ten,i);//sum of digits,rest=((a.get_numero())[i]+(b.get_numero())[i]+rest)/ten;// rest is saving suming over 10

    }
    if(a_size>b_size)//to find which number is greater
    for(int i=min(a_size,b_size);i<a_size;i++)//part where one numbers has no digit -> is less
    {
        //res.get_numero().push_back((a.get_numero()[i]+rest)%10);//set zero at the higher positions of the smallest number
        res.set_numero((a.get_numero()[i]+rest)%ten,i);
        rest=((a.get_numero())[i]+rest)/ten;
    }   
    else
    for(int i=min(a_size,b_size);i<b_size;i++)
    {
        //res.get_numero().push_back(((b.get_numero())[i]+rest)%10);
        res.set_numero(((b.get_numero())[i]+rest)%ten,i);
        rest=((b.get_numero())[i]+rest)/ten;
    }
    if(rest!=0)//if the result has more digit than the greatest partner
    {
        //res.get_numero().push_back(rest);
        res.set_numero(rest,max(a_size,b_size));
    }
    if((res.numero[(res.numero).size()-1])==0)//reduces zero digit from left if possible
        (res.numero).erase((res.numero).end()-1);
    
return res;
}

ostream& operator<< (ostream& out,const long_number& num)//output of the number
{
    for(int i=(num.numero).size()-1;i>=0;i--)
    {
        out << (num.numero)[i];
    }
    return out;
}

void long_number::read(string input)
{
    //if(this->numero)
        this->numero.erase(this->numero.cbegin(),this->numero.cend());
    string s;
    if(typeid (input)== typeid (string))
        string s = input;
    else
        ;
    //string s = to_string(input);
    for(int i=input.size()-1;i>=0;i--)
        (this->numero).push_back(input[i]-'0');
    this->size = (this->numero).size();
}

void long_number::get(ostream& out) const
{
    for(int i=(this->numero).size()-1;i>=0;i--)
    {
        out << (this->numero)[i];
    }
    //out << endl;
}
}

我知道可以使用更快的算法进行求和,但是我使用了标准的逐位求和,但是我没想到差异会那么大。 速度是算法真正给定的吗?与标准数据类型相比,最高速度是多少?在我的代码中,有没有哪个地方可以更好地优化以加速代码执行?还是可以在编译器命令中使用更多标志以提高性能

我真的很感谢我的一切帮助!!! 弗兰克

解决方法

通过消除long_number operator+中向量的多个副本,可以轻松地改善您的get_numero()

您并不需要真正复制矢量来询问其大小。只需为您的课程提供一个size()方法即可。

类似地,代替(a.get_numero())[i](再次在索引整个向量之前对其进行复制),实现operator []以直接访问各个数字。

该添加量长1000倍-很多!但是,预计会达到100倍左右-只需算一下您有多少步即可代替一条简单的add指令