5

私が本当に説明したくない巧妙で複雑な理由のために(それは非常に醜くてハッキーな方法でタイマーを作ることを含むので)、私は次のようなC#コードを書きました:

int i = 0;
while (i >= 0) i++; //Should increment forever
Console.Write(i);

プログラムが永久にハングしたり、クラッシュしたりすることを期待していましたが、驚いたことに、約20秒待った後、次の出力が表示されます。

-2147483648

プログラミングは私に多くのことを教えてくれましたが、数を増やし続けると最終的に負になる理由をまだ理解できません...ここで何が起こっているのでしょうか?

4

9 に答える 9

12

C#では、組み込みの整数は、事前定義された長さのビット値のシーケンスで表されます。基本intデータ型の場合、その長さは32ビットです。32ビットは4,294,967,296の異なる可能な値しか表すことができないため(2 ^ 32であるため)、コードが継続的に増加する値で永久ループすることはありません。

int正の数と負の数の両方を保持できるため、数の符号を何らかの方法でエンコードする必要があります。これは最初のビットで行われます。最初のビットが1の場合、数値は負です。

16進数と10進数の数直線上に配置されたint値は次のとおりです。

 Hexadecimal        Decimal
 -----------    -----------
 0x80000000     -2147483648
 0x80000001     -2147483647
 0x80000002     -2147483646
    ...              ...
 0xFFFFFFFE              -2
 0xFFFFFFFF              -1
 0x00000000               0
 0x00000001               1
 0x00000002               2
     ...             ...
 0x7FFFFFFE      2147483646
 0x7FFFFFFF      2147483647

このグラフからわかるように、可能な最小値を表すビットは、符号ビットの解釈を無視して、可能な最大値に1を加算することによって得られるものです。このように符号付き数値を加算すると、「整数の桁あふれ」と呼ばれます。整数のオーバーフローが許可されるか、エラーとして扱われるかどうかは、C#のcheckedandステートメントで構成できます。uncheckedデフォルトはチェックされていないので、エラーは発生しませんでしたが、プログラムにそのクレイジーな少数が含まれています。

この表現2の補数と呼ばれます。

于 2011-05-31T22:20:12.750 に答える
8

0xFFFFFFFF値は、10進数で-2147483648になる32ビット整数ストレージの正の範囲をオーバーフローしています。これは、31ビット整数でオーバーフローすることを意味します。

unsigned intを使用すると、32番目のビットが数値の符号を格納するために使用されていないため、異なる動作が発生することが他に指摘されています。

于 2011-05-31T22:07:39.450 に答える
2

あなたが経験しているのは整数のオーバーフローです。

コンピュータプログラミングでは、算術演算が使用可能な記憶域内で表現できるよりも大きい数値を作成しようとすると、整数のオーバーフローが発生します。たとえば、表現できる最大値に1を加算すると、整数のオーバーフローが構成されます。これらの場合の最も一般的な結果は、結果の最下位の表現可能なビットが格納されることです(結果はラップすると言われます)。

于 2011-05-31T22:05:39.350 に答える
2

int符号付き整数です。最大値を超えると、最小値(大きな負の値)から始まり、0に向かって進みます。

でもう一度試してuint、何が違うかを確認してください。

于 2011-05-31T22:07:23.643 に答える
2

このようにしてみてください:

int i = 0;
while (i >= 0) 
   checked{ i++; } //Should increment forever
Console.Write(i);

そして結果を説明する

于 2011-05-31T22:07:31.750 に答える
2

他の人が言っていること。永遠に続くことができるものが必要な場合(そして、なぜこの種のものが必要になるのかについては触れません)、System.Numerics名前空間(.NET 4+)のBigIntegerクラスを使用します。任意の数との比較ができます。

于 2011-05-31T22:08:17.663 に答える
0

これは、変数「i」が最大int制限に達すると、次の値が負の値になるために発生します。

于 2011-05-31T22:08:09.207 に答える
0

これは、正の数と負の数が実際にメモリに(ビットレベルで)どのように格納されるかと大きく関係しています。

興味のある方は、このビデオをチェックしてください: 12: 25以降のプログラミングパラダイム。非常に興味深いので、コードがそのように動作する理由を理解できます。

于 2011-05-31T22:12:58.927 に答える
-1

私はこれが賢いお尻のアドバイスのように聞こえないことを願っています。

あなたが求めているのは、整数データ型のかなり基本的な動作であるものを説明することです。

コンピュータサイエンスコースの1年目にデータ型がカバーされるのには理由があります。これは、問題が発生する方法と場所を理解するための非常に基本的なことです(予期しない動作が予期しない動作、つまりバグを引き起こした場合、上記の動作がどのように発生するかはすでにわかります。あなたの申請)。

私のアドバイスは、1年目のコンピューターサイエンス+クヌースの独創的な作品「コンピュータープラグラミングの芸術」の読み物を手に入れることです。約500ドルで、Uniコース全体よりもはるかに安価な優れたプログラマーになるために必要なすべてのものを手に入れることができます;- )。

于 2011-05-31T22:28:52.583 に答える