C ++:大整数

时间:2009-02-20 01:32:34

标签: c++ flex-lexer

我正在编写词法分析器作为编译器项目的一部分,我需要检测一个整数是否大于int中的整数,以便我可以打印错误。是否有适合此目的的大整数C ++标准库?

9 个答案:

答案 0 :(得分:10)

用于将数字字符串转换为整数的标准C库函数应该检测超出范围的数字,并将errno设置为ERANGE以指示问题。见here

答案 1 :(得分:5)

你可能会使用libgmp。但是,我认为只是为了你的目的,这是不必要的。

例如,如果您将数字解析为32位unsigned int,那么

  1. 解析第一个最多9个十进制数字(即楼层(32 * log(2)/ log(10))。如果还没有,则数字正常。
  2. 采取下一个数字。如果你得到的数字/ 10不等于上一步的数字,那么数字就不好了。
  3. 如果您有更多数字(例如,超过9 + 1),则数字很差。
  4. 否则数字很好。
  5. 请务必跳过任何前导零等。

答案 2 :(得分:3)

libgmp是一个通用的解决方案,虽然可能有点重量级。

对于重量较轻的词法分析器,您可以将其视为一个字符串;修剪前导零,然后如果它超过10位数,则它太长;如果更短则可以,如果正好是10位数,则字符串与最大值2 ^ 31 = 2147483648或2 ^ 32 = 4294967296进行比较。请记住,-2 ^ 31是合法值,但2 ^ 31不是。还要记住八进制和十六进制常量的语法。

答案 3 :(得分:1)

这个怎么样?使用atol,检查溢出和下溢。

#include <iostream>
#include <string>

using namespace std;

main()
{
    string str;
    cin >> str;
    int i = atol(str.c_str());
    if (i == INT_MIN && str != "-2147483648") {
        cout << "Underflow" << endl;
    } else if (i == INT_MAX && str != "2147483647") {
        cout << "Overflow" << endl;
    } else {
        cout << "In range" << endl;
    }   
}

答案 4 :(得分:1)

向所有人建议atoi:

  • 我的atoi()实现没有设置errno。
  • 我的atoi()实现在溢出时不返回INT_MIN或INT_MAX。
  • 我们不能依赖牌子逆转。考虑0x4000 ... 0。
    • * 2并设置负位。
    • * 4且值为零。
    • 对于基数为10的数字,我们的下一个数字会乘以10。

这都是坚果。除非您的词法分析器正在解析数字数据的演出,否则请停止过早优化。它只会导致悲伤。

这种方法可能效率低下,但足够满足您的需求:

const char * p = "1234567890123";
int i = atoi( p );

ostringstream o;
o << i;
return o.str() == p;

或者,利用堆栈:

const char * p = "1234567890123";
int i = atoi( p );

char buffer [ 12 ];
snprintf( buffer, 12, "%d", i );
return strcmp(buffer,p) == 0;

答案 5 :(得分:0)

如果您希望能够处理此类号码,可能需要查看GMP

答案 6 :(得分:0)

在解析整数字符串的词法分析器中,在添加每个新数字之前必须乘以10(假设您从左到右进行解析)。如果该运行总计突然变为负数,则超出整数的精度。

答案 7 :(得分:0)

如果您的语言(如C)支持表达式的编译时评估,那么您可能也需要考虑这一点。

这样的东西:

#define N 2147483643  // This is 2^31-5, i.e. close to the limit.

int toobig = N + N;

GCC会抓住这个,说“警告:表达式中的整数溢出”,但当然没有单个文字溢出。这可能比你要求的更多,只是想我会指出它是真正的编译器在这个部门的东西。

答案 8 :(得分:-1)

您可以检查数字是分别高于还是低于INT_MAX或INT_MIN。您需要#include <limits.h>