【问题标题】:Arbitrary size integers in C/C++C/C++ 中的任意大小整数
【发布时间】:2015-04-25 11:39:43
【问题描述】:

问题

  • 有没有办法使用 c/c++ 创建任意大小的整数?

例如:

int main(void) {
  Int i = Int(3); //3-bit integer
  i = 1; //Represented as: 001
}

奖金

  • 有没有办法对浮点值做同样的事情?

【问题讨论】:

  • 你可以写一个类来做这个。
  • 不是单独的,而是作为结构或类的一部分:bit field
  • 如果您尝试在任意大小的浮点类中执行1/3,您将遇到堆栈溢出!
  • 在这里查看任意大小的小整数:stackoverflow.com/questions/11815894/…,如果您对节省内存感兴趣(位打包会带来小的性能损失)。对于比标准类型更大的类型,您最好使用一些库。
  • 仅供参考,有一个 C23 提案(open-std.org/jtc1/sc22/wg14/www/docs/n2709.pdf“为 N 位整数添加基本类型”)通过 _BitInt(3) 添加它们。如果获得批准,这可能是未来的另一个答案。

标签: c++ c integer


【解决方案1】:

您可以试试GNU Multiple Precision Arithmetic Library 库,它支持整数、分数和实数。

【讨论】:

  • 我可以用 gmp 创建一个固定大小的整数吗?对于我正在阅读的内容,这会创建类似 python 的整数,只要它们具有所需的内存,它们就会增长。
  • @SimonOroño:至少对于浮点支持,看起来您指定了要使用的位数:mpfr.org/sample.html
  • 答案是缺少“小于一个字节”的方面。
  • @SimonOroño 啊哈;我没有意识到子字节大小对你很重要。
  • @SimonOroño 如果你想要固定宽度的整数/浮点类型,那么你应该使用ttmathboost::multiprecision
【解决方案2】:

不,每个原始元素(int、short、long...)的大小取决于硬件架构。

对于更大的尺寸,您应该使用一个 Big Integer 库(它们用字符串表示数字)。

【讨论】:

  • 您能否详细说明“字符串”的含义?
  • 例如:“94314”。字符串可以有一个任意大小,所以你可以有更大的数字。
  • 问题是重新定义算术运算。 @尼尔柯克
  • 为什么不用一定大小的整数数组来表示任意整数?这将比文本字符串快得多。
  • “不,每个原始元素(int、short、long ...)的大小取决于硬件架构。”嗯 - 使用相同的硬件平台,我可以使用各种编译器和选项设置,并控制char(有符号或无符号)、int(16 或 32)、long(32 或 64 位)的范围.我会说编译器具有最终控制权。而不是硬件。
【解决方案3】:

您可以围绕std::bitsetstd::vector<bool> 编写一个包装类。这些是位容器。

您的类将包含其中一个容器并添加与整数相互转换的功能;以及其他算术运算。

这将允许您拥有不寻常的位大小的整数,例如 3、5 和 13。

大多数实现将四舍五入到最接近的 8 倍数或处理器的字长。 3 位的容器将使用带有 5 个未使用位的uint8_t,主要是因为处理器更容易操作。 13 位整数将驻留在 16 位包中。

编辑 1:浮点数
除非您符合 标准 浮点格式,否则您将不得不编写自己的包装类。这将允许您拥有 3 位尾数、5 位指数和 1 位符号 - 9 位。再次考虑一下您需要编写的所有方法。大多数应用程序将使用doublefloat,因为不需要编写单独的包装器,这会花费编码时间和测试时间。

【讨论】:

  • 环绕bitsetvector<bool> 将不必要地缓慢和复杂。 Bitsets 甚至不支持动态大小,它必须在编译时知道。
  • 自定义位大小的变量将不必要地缓慢和复杂,因为位设置、清除、提取和打包。 bitsetvector<bool> 是方便的容器。
  • 根据要求,您可以使用比基于单个位的容​​器效率更高的容器。
  • 为什么位容器比较慢?什么会更有效率? @ddriver
  • 具有讽刺意味的是,在现代硬件上,64 位整数运算通常需要一个时钟周期,而位访问单独访问需要 2-3 个周期,而您仍然需要进行实际操作。计算机至少可以寻址一个字节,因此低于字节总是会产生提取值所需的按位运算开销。
【解决方案4】:

您不能创建大小小于char 的整数(也就是说,每个对象的字节大小是sizeof(char) 的倍数,即1)。但这不是问题,因为您可以将数字包含在更大的数字中。

const unsigned size_in_bits = 3;
unsigned a = 1; // 001
unsigned b = 5; // 101
unsigned packed = (b << size_in_bits*1) | (a << size_in_bits*0); // 101001
unsigned unpacked_a = (packed >> size_in_bits*0) & ((1 << size_in_bits)-1);
unsigned unpacked_b = (packed >> size_in_bits*1) & ((1 << size_in_bits)-1);

或使用位域(语法更好,但二进制布局是实现定义的)

struct Date
{
    unsigned day : 5;
    unsigned month : 4;
    unsigned year : 21; 
};

Date d;
d.day = 5; d.month = 11; d.year = 2014;

【讨论】:

  • 能否详细说明“二进制布局是实现定义的”?
  • @SimonOroño - 不能保证不同的编译器会产生相同的布局。该标准使与异国平台兼容的“非标准化”早已不复存在。如果您想要可移植性,您最好编写自己的“手动位域”,如我在上面的 cmets 中链接的问题中所述。
【解决方案5】:

解释:


您总是可以尝试使用数组来使用整数和浮点数操作。如果数组初始化太大,可以使用malloc();函数。

请注意:此方法不是很快,因为我们将在堆中分配内存。您还必须编写自己的数学运算函数,因为我不太确定如何有效地实现它。 见下文


如何实现(有点):


#include <stdio.h>
#include <stdlib.h>

#define MAX_DIGIT_COUNT 1000

int main()
{
    int* big_num = (int*)malloc(sizeof(int) * MAX_DIGIT_COUNT); //allocate memory
    for(int x; x<MAX_DIGIT_COUNT; x++)
    {
        /*
        *Iterating through number - iterating works, because we are basing out max number lenght 
        *off of the maximum digits, and therefore, we can have a maximum of 2^64 digits
        */
        big_num[x] = rand()%5; //fill up memory block with psuedo-random numbers
    }
    /*Printing begins here...*/
    for(int i; i<MAX_DIGIT_COUNT; i++)
    {
        int iterated;
        iterated = big_num[i];
        printf("%d", iterated);
    }
    printf("\n");
    /*Printing ends here*/
    return 0;
}

请注意:这只是在纯 C 中实现任意大小的数字支持的一种粗略方式。

【讨论】:

  • 对了,你可以使用char arrays来提高内存效率...
猜你喜欢
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多