web-dev-qa-db-ja.com

なぜ無限大= 0x3f3f3f3fなのですか?

状況によっては、通常、無限大を表すのに十分な大きさの整数値を使用します。私は通常、表現可能な最大の正/負の整数を使用します。オーバーフローを回避するために、実質的にすべての算術演算の前に、オペランドの1つが無限大であるかどうかを確認する必要があるため、通常はより多くのコードが生成されます。飽和した整数演算が望ましい場合があります。そのため、無限大に小さい値を使用する人もいます。これは、オーバーフローすることなく数回加算または乗算できます。私が興味をそそられるのは、(特にプログラミング競技会で)見ることが非常に一般的であるという事実です。

const int INF = 0x3f3f3f3f;

その数が特別なのはなぜですか?バイナリ表現は次のとおりです。

00111111001111110011111100111111

ここには特に興味深い物件はありません。入力は簡単だと思いますが、それが理由であれば、ほとんど何でもできます(0x3e3e3e3e、0x2f2f2f2fなど)。オーバーフローすることなく一度追加できます。これにより、次のことが可能になります。

a = min(INF, b + c);

しかし、他のすべての定数で十分です。グーグルすると、その定数を使用する多くのコードスニペットのみが表示され、説明やコメントは表示されません。

誰かがそれを見つけることができますか?

22
Gabriel

私はこれについていくつかの証拠を見つけました ここ元の内容 中国語で);基本的な考え方は、0x7fffffffはすでに4バイトのsigned intの範囲の「トップ」であるため、問題があるということです。したがって、それに何かを追加すると、負の数になります。代わりに、0x3f3f3f3f:

  • まだかなり大きいです(0x7fffffffの同じ桁)。
  • 十分な余裕があります。整数の有効な範囲がその下の数に制限されていると言う場合は、それに「有効な正の数」を追加しても、無限大を取得できます(つまり、何か>=INF)。でもINF+INFオーバーフローしません。これにより、常に「制御下」に保つことができます。

    a+=b;
    if(a>INF)
        a=INF;
    
  • 等しいバイトの繰り返しです。つまり、memsetのものをINFに簡単に追加できます。

  • また、@JörgWMittagが上で気づいたように、それはニースASCII表現を持っており、メモリダンプを見てその場でそれを見つけ、メモリに直接書き込むことができます。
25
Matteo Italia

私は0x3f3f3f3fの最も早い発見者の1人であるかもしれないしそうでないかもしれません。 2004年にルーマニアの記事を公開しました( http://www.infoarena.ro/12-ponturi-pentru-programatorii-cc #9)が、2002年からこの値を使用しています。少なくともプログラミング競技では。

それには2つの理由があります。

  • 0x3f3f3f3f + 0x3f3f3f3fはint32をオーバーフローしません。このために、100000000(10億)を使用するものもあります。
  • memset(array, 0x3f, sizeof(array))を実行すると、intの配列を無限大に設定できます。
11
Alexandru

0x3f3f3f3fは文字列のASCII表現????

Krugleは、データベース全体でその定数の48個のインスタンスを見つけます。これらのインスタンスのうち46個はJavaプロジェクトにあり、グラフィック操作のビットマスクとして使用されます。

1つのプロジェクトはオペレーティングシステムであり、未知のACPIデバイスを表すために使用されます。

1つのプロジェクトもJavaグラフィックスのビットマスクです。

したがって、Krugleによってインデックス付けされたすべてのプロジェクトで、ビットパターンのために47回使用され、ASCII解釈のために、1回ではなく、無限の表現として1回使用されます。

9
Jörg W Mittag