1. ホーム
  2. c

[解決済み] なぜ無限大=0x3f3f3fなのですか?

2022-02-15 20:19:35

質問

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

const int INF = 0x3f3f3f3f;

なぜその数字が特別なのか?それは、2進数表現が

00111111001111110011111100111111

特に面白い特性は見当たりませんね。入力が簡単なのはわかるが、それが理由ならほとんど何でもいい(0x3e3e3e、0x2f2f2f、など)。オーバーフローすることなく一度だけ追加することができる、それが可能です。

a = min(INF, b + c);

でも、それなら他の定数でもいいんじゃない?ググっても、その定数を使ったコードスニペットがたくさん出てくるだけで、説明やコメントがない。

どなたか見分けられる方いらっしゃいますか?

解決方法は?

この件に関して、いくつかの証拠を見つけました。 こちら ( オリジナルコンテンツ 基本的な考え方は、0x7fffffffはすでに4バイト符号付きintの範囲の最上位なので問題があり、これに何かを加えると負の数、0x3f3f3fになる、というものです。

  • はまだかなり大きいです(0x7fffffと同じ桁)。
  • 整数の有効範囲がこれより下の数字に限られていると言うなら、これに任意の "有効な正の数" を加えても、無限(つまり、何か >=INF ). 偶数 INF+INF はオーバーフローしない。これによって、常に "under control" を保つことができます。

    a+=b;
    if(a>INF)
        a=INF;
    
    
  • は等バイトの繰り返しなので、簡単に memset に詰め込む。 INF ;

  • また、@Jörg W Mittag が上で気づいたように、素敵な ASCII 表現を持っているので、メモリダンプを見ながらその場で発見することも、メモリに直接書き込むことも可能です。