私はコンパイラ プロジェクトの一部としてレクサーを作成しています。エラーを出力できるように、整数が int に収まるサイズよりも大きいかどうかを検出する必要があります。この目的に適合する大整数用の C++ 標準ライブラリはありますか?
9 に答える
数値文字列を整数に変換するための標準 C ライブラリ関数は、範囲外の数値を検出し、errno を ERANGE に設定して問題を示すと想定されています。こちらをご覧ください
おそらくlibgmpを使用できます。しかし、私はあなたの目的のために、それは不必要だと思います。
たとえば、数値を 32 ビットの unsigned int に解析する場合、
- 最初の最大 9 個の 10 進数を解析します (つまり、floor(32*log(2)/log(10))。それ以上ない場合は、その数値で問題ありません。
- 次の桁を取ります。得られた数 / 10 が前のステップの数と等しくない場合、その数は悪いです。
- 桁数が多い場合 (例: 9+1 を超える場合)、その数字は不適切です。
- それ以外の数は良好です。
先頭のゼロなどは必ずスキップしてください。
libgmp は一般的なソリューションですが、少し重いかもしれません。
軽量の字句解析器の場合は、文字列として扱うことができます。先頭のゼロを削除し、10 桁を超える場合は長すぎます。それより短い場合は問題ありません。正確に 10 桁の場合、文字列は最大値 2^31=2147483648 または 2^32=4294967296 と比較されます。-2^31 は正当な値ですが、2^31 はそうではないことに注意してください。また、8 進定数と 16 進定数の構文にも注意してください。
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;
これはどう。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;
}
}
お使いの言語(Cなど)が式のコンパイル時評価をサポートしている場合は、それについても考慮する必要があります。
このようなもの:
#define N 2147483643 // This is 2^31-5, i.e. close to the limit.
int toobig = N + N;
GCCはこれをキャッチし、「警告:式の整数オーバーフロー」と言いますが、もちろん、個々のリテラルがオーバーフローすることはありません。これはあなたが必要とする以上のものかもしれませんが、私がこの部門で実際のコンパイラーが指摘するものとして指摘したいと思います。
レクサーでは、整数文字列を解析するときに、新しい数字を追加する前に 10 を掛ける必要があります (左から右に解析していると仮定します)。その現在の合計が突然負になる場合は、整数の精度を超えています。
そのような数値を処理できるようにしたい場合は、GMPを調べてみてください。
数値がそれぞれ INT_MAX または INT_MIN より大きいか小さいかを確認できます。あなたがする必要があります#include <limits.h>