4

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

4

9 回答 9

10

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

于 2009-02-20T01:46:10.767 回答
5

您可能可以使用 libgmp。但是,我认为出于您的目的,这只是不必要的。

例如,如果您将数字解析为 32 位无符号整数,则

  1. 解析第一个最多 9 个十进制数(即 floor(32*log(2)/log(10))。如果没有更多,则该数字是可以的。
  2. 取下一个数字。如果你得到的数字 / 10 不等于上一步的数字,那么这个数字就是坏的。
  3. 如果您有更多数字(例如,超过 9+1),则数字不好。
  4. 否则数字是好的。

请务必跳过任何前导零等。

于 2009-02-20T01:47:17.537 回答
3

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

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

于 2009-02-20T02:19:23.620 回答
1

对于所有建议atoi的人:

  • 我的 atoi() 实现没有设置 errno。
  • 我的 atoi() 实现不会在溢出时返回 INT_MIN 或 INT_MAX。
  • 我们不能依赖符号反转。考虑 0x4000...0。
    • *2 并设置负位。
    • *4 且值为 0。
    • 使用以 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;
于 2009-02-20T03:52:25.613 回答
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;
    }   
}
于 2009-02-20T03:11:28.597 回答
0

如果您希望能够处理此类数字,您可能需要查看GMP 。

于 2009-02-20T01:42:50.650 回答
0

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

于 2009-02-20T01:49:45.487 回答
0

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

像这样的东西:

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

int toobig = N + N;

GCC 会捕捉到这一点,说“警告:表达式中的整数溢出”,但当然没有个别文字溢出。这可能超出了您的要求,只是想我会指出它是该部门真正的编译器需要的东西。

于 2009-02-20T10:38:15.420 回答
-1

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

于 2009-02-20T01:44:48.367 回答