状況によっては、通常、無限大を表すのに十分な大きさの整数値を使用します。私は通常、表現可能な最大の正/負の整数を使用します。オーバーフローを回避するために、実質的にすべての算術演算の前に、オペランドの1つが無限大であるかどうかを確認する必要があるため、通常はより多くのコードが生成されます。飽和した整数演算が望ましい場合があります。そのため、無限大に小さい値を使用する人もいます。これは、オーバーフローすることなく数回加算または乗算できます。私が興味をそそられるのは、(特にプログラミング競技会で)見ることが非常に一般的であるという事実です。
const int INF = 0x3f3f3f3f;
その数が特別なのはなぜですか?バイナリ表現は次のとおりです。
00111111001111110011111100111111
ここには特に興味深い物件はありません。入力は簡単だと思いますが、それが理由であれば、ほとんど何でもできます(0x3e3e3e3e、0x2f2f2f2fなど)。オーバーフローすることなく一度追加できます。これにより、次のことが可能になります。
a = min(INF, b + c);
しかし、他のすべての定数で十分です。グーグルすると、その定数を使用する多くのコードスニペットのみが表示され、説明やコメントは表示されません。
誰かがそれを見つけることができますか?
私はこれについていくつかの証拠を見つけました ここ ( 元の内容 中国語で);基本的な考え方は、0x7fffffffはすでに4バイトのsigned intの範囲の「トップ」であるため、問題があるということです。したがって、それに何かを追加すると、負の数になります。代わりに、0x3f3f3f3f:
十分な余裕があります。整数の有効な範囲がその下の数に制限されていると言う場合は、それに「有効な正の数」を追加しても、無限大を取得できます(つまり、何か>=INF
)。でもINF+INF
オーバーフローしません。これにより、常に「制御下」に保つことができます。
a+=b;
if(a>INF)
a=INF;
等しいバイトの繰り返しです。つまり、memset
のものをINF
に簡単に追加できます。
私は0x3f3f3f3fの最も早い発見者の1人であるかもしれないしそうでないかもしれません。 2004年にルーマニアの記事を公開しました( http://www.infoarena.ro/12-ponturi-pentru-programatorii-cc #9)が、2002年からこの値を使用しています。少なくともプログラミング競技では。
それには2つの理由があります。
memset(array, 0x3f, sizeof(array))
を実行すると、intの配列を無限大に設定できます。0x3f3f3f3f
は文字列のASCII表現????
。
Krugleは、データベース全体でその定数の48個のインスタンスを見つけます。これらのインスタンスのうち46個はJavaプロジェクトにあり、グラフィック操作のビットマスクとして使用されます。
1つのプロジェクトはオペレーティングシステムであり、未知のACPIデバイスを表すために使用されます。
1つのプロジェクトもJavaグラフィックスのビットマスクです。
したがって、Krugleによってインデックス付けされたすべてのプロジェクトで、ビットパターンのために47回使用され、ASCII解釈のために、1回ではなく、無限の表現として1回使用されます。