如何在整数数组中有效存储大量数? C ++

时间:2018-05-18 14:46:04

标签: c++ arrays string integer

大家好!我有一个家庭工作分配,我需要建立一个高数字的高预设计算器。这个分配的重点是现在允许将值存储在数组中作为一个数字进入单独的数组单元格。

这是数字的内存表示

335897294593872

喜欢这样

int number[] = {3, 3, 5, 8, 9, 7, 2, 9, 4, 5, 9, 3, 8, 7, 2};

不合法,

,也不

char number[] = {3, 3, 5, 8, 9, 7, 2, 9, 4, 5, 9, 3, 8, 7, 2};

,也不

std::string number("335897294593872");

我想要做的是将整个数字拆分为32位块,并将每个块存储在单独的数组单元格数据类型中,即u32int_t。

由于我从键盘获取输入,我最初将所有值存储在std :: string中,然后将它们放在整数数组中以执行操作。

如何将一个大数字的二进制表示放入一个正确填充所有位的整数数组?

提前谢谢。

编辑:仅使用标准C ++库

EDIT2:我希望能够对这些数组进行加,减,乘,除,所以我的意思是不仅仅是剪切字符串并将十进制表示存储在整数数组中,而是保留数字本身的位顺序能够计算结转。

3 个答案:

答案 0 :(得分:1)

这是一个相当天真的解决方案:

  1. 如果字符串中的最后一位数字为奇数,则存储结果为1(否则为0)。
  2. 将字符串中的数字除以2(考虑进位)。
  3. 如果已写入32位,则向结果向量添加另一个元素。
  4. 重复此操作,直到字符串仅包含0。
  5. 源代码:

    #include <iomanip>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    
    std::vector<uint32_t> toBigInt(std::string text)
    {
      // convert string to BCD-like
      for (char &c : text) c -= '0';
      // build result vector
      std::vector<uint32_t> value(1, 0);
      uint32_t bit = 1;
      for (;;) {
        // set next bit if last digit is odd
        if (text.back() & 1) value.back() |= bit;
        // divide BCD-like by 2
        bool notNull = false; int carry = 0;
        for (char &c : text) {
          const int carryNew = c & 1;
          c /= 2; c += carry * 5;
          carry = carryNew;
          notNull |= c;
        }
        if (!notNull) break;
        // shift bit
        bit <<= 1;
        if (!bit) {
          value.push_back(0); bit = 1;
        }
      }
      // done
      return value;
    }
    
    std::ostream& operator<<(std::ostream &out, const std::vector<uint32_t> &value)
    {
      std::ios fmtOld(0); fmtOld.copyfmt(out);
      for (size_t i = value.size(); i--;) {
        out << std::hex << value[i] << std::setfill('0') << std::setw(sizeof (uint32_t) * 2);
      }
      out.copyfmt(fmtOld);
      return out;
    }
    
    int main()
    {
      std::string tests[] = {
        "0", "1",
        "4294967295", // 0xffffffff
        "4294967296", // 0x100000000
        "18446744073709551615", // 0xffffffffffffff
        "18446744073709551616", // 0x100000000000000
      };
      for (const std::string &test : tests) {
        std::cout << test << ": " << toBigInt(test) << '\n';
      }
      return 0;
    }
    

    输出:

    0: 0
    1: 1
    4294967295: ffffffff
    4294967296: 100000000
    18446744073709551615: ffffffffffffffff
    18446744073709551616: 10000000000000000
    

    Live Demo on coliru

    备注:

    1. 输出是little-endian。 (最重要的元素是第一个。)
    2. 对于tests,我使用了数字,其中十六进制代码很容易用眼睛检查。

答案 1 :(得分:1)

使用数组存储大数字的不同部分是完成工作的常用方法。另一件需要考虑的事情是考虑signed int的不同架构实现,这导致你必须牺牲(这是处理大整数的正常库所做的),以允许signed到{{在您的数字部分之间转换(您有几种方法)或者您将如何实现不同的算术运算。

我通常不建议对数组单元使用unsigned整数版本,因为它们通常不是架构的原生大小,因此为了给架构提供一些有效处理事物的机会,我应该使用简化(至少一位,以便扩展数字执行到下一个<)>标准long long(例如, gnu ** libgmp *在每个阵列单元格上使用24位整数---上次我检查过它。将它减少到unsigned大小的倍数也很常见,因此数字的位移和重新分配比在完整的位数组上进行char位移更容易。

答案 2 :(得分:0)

通常情况下,当你使用金钱或类似的精巧数字时,你经常使用整数,因为你可以保证很多东西,所以我的建议是每当你使用这个大数字时,模拟一个具有两个Int的固定点或浮点算术,因此您可以观察&#34;如何执行一切,您可以检查浮点的IEEE 754标准。 如果将数字存储在数组中,请确保采取一​​定数量的步骤来执行操作时所执行的所有操作。这可能很棘手。

我建议你相信整数,但要修改位的大小。 但是如果你真的想要寻找有趣的东西,那就尝试使用逐位运算符,也许你可以得到一些有趣的东西。

您可以查看数据类型here的详细信息,尤其是signed short intlong long int,并确认数据类型的大小检查this