为大无符号整数分配内存的有效方法

时间:2017-06-18 19:00:06

标签: c++ performance optimization biginteger

我为包含最多10^5个十进制数字的大无符号整数编写了一个C ++类,它内部有一个BASE = 10^9std::vector<long long>来存储实际数字 -

例如754564575693573452存储为

std::vector<long long> number = {693573452, 754564575}

在构造函数中,我调整此向量的大小以始终包含一些固定数量的long long数字,例如它的10 ^ 5,因此单个添加两个大的uint可以有多达10 ^ 6位数(在9 * 10^6数字系统中是BASE = 10^1个数字,并且类似于乘法......

因此所有算术运算的速度都提高了9倍,但这只是针对大数字的一些计算而注意到的,对于有大量计算的情况,性能会降低,这是因为类设计,我的构造函数和默认构造函数总是调用resize函数,如前所述,这是线性时间例程。

void Big_uint::read_num_str(const std::string& num_str)
{
    // reading from num_str to number
}

Big_uint::Big_uint(const std::string& num_str = "0")
{
    number.resize( 1000000 );
    read_num_str(num_str);  
}

Big_uint::Big_uint(const long long& num)
{
    number.resize( 1000000 );
    char buff[ 20 ];
    _itoa_s(static_cast<int>(num), buff, 10);
    std::string s = buff;
    read_num_str(s);    
}

并且所有算术运算都以这种方式实现

Big_uint operator + (const Big_uint& left, const Big_uint& right)
{
    Big_uint res; // resize() called here to initialize a vector
    // add algorithm
    return res; 
}

Big_uint operator * (const Big_uint& left, const Big_uint& right)
{
    Big_uint res; // resize() called here to initialize a vector

    // some multiplication algorithm here (currently only naive O(n^2) implemented)

    return res; 
}

因此,它们效率低下。

如何根据运算符重载的输入初始化向量?

我不想将运算符重载更改为add, mul, div之类的成员函数,并将它们传递给3个参数,其中第3个参数为res - 预先分配的零初始化Big_uint为存储二进制运算的结果。

1 个答案:

答案 0 :(得分:3)

您不应该以这种方式预先分配存储空间。根本不要预先分配。在每次操作中,您都知道(大约)结果的大小。对于添加,它是输入大小加上一个的最大值。对于mul,它是输入大小的总和。始终尝试仅分配必要的空间来容纳数字。

因此,默认构造函数根本不应该分配。每个其他构造函数都应该检查输入的大小,并分配必要的空间。操作员应(保守地)估计必要的空间,并相应地进行分配。

旁注:您应该使用base 2 ^ 32而不是10 ^ 9(或64位计算机上的2 ^ 64):它的内存消耗略少,性能会更好。

附注2:sizeof(long long)通常是8,所以如果只存储小于10 ^ 9的数字,就会浪费内存。