4

私はコンパイラ プロジェクトの一部としてレクサーを作成しています。エラーを出力できるように、整数が int に収まるサイズよりも大きいかどうかを検出する必要があります。この目的に適合する大整数用の C++ 標準ライブラリはありますか?

4

9 に答える 9

10

数値文字列を整数に変換するための標準 C ライブラリ関数は、範囲外の数値を検出し、errno を ERANGE に設定して問題を示すと想定されています。こちらをご覧ください

于 2009-02-20T01:46:10.767 に答える
5

おそらくlibgmpを使用できます。しかし、私はあなたの目的のために、それは不必要だと思います。

たとえば、数値を 32 ビットの unsigned int に解析する場合、

  1. 最初の最大 9 個の 10 進数を解析します (つまり、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 はそうではないことに注意してください。また、8 進定数と 16 進定数の構文にも注意してください。

于 2009-02-20T02:19:23.620 に答える
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;
于 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

お使いの言語(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 に答える
0

レクサーでは、整数文字列を解析するときに、新しい数字を追加する前に 10 を掛ける必要があります (左から右に解析していると仮定します)。その現在の合計が突然負になる場合は、整数の精度を超えています。

于 2009-02-20T01:49:45.487 に答える
0

そのような数値を処理できるようにしたい場合は、GMPを調べてみてください。

于 2009-02-20T01:42:50.650 に答える
-1

数値がそれぞれ INT_MAX または INT_MIN より大きいか小さいかを確認できます。あなたがする必要があります#include <limits.h>

于 2009-02-20T01:44:48.367 に答える