Project Euler (ちなみに素晴らしいサイト)で問題番号10についてこの奇妙な経験をしました。割り当ては、200万未満のすべての素数の合計を計算することでした。
私は合計にintを使用し、私のアルゴリズムは答えを生成しましたが、答えを確認するためにそれを貼り付けたとき、それは間違っていました。
結果が大きすぎてintに収まらないことが判明しましたが、これはオーバーフローエラーなどを引き起こしませんか?代わりに、実際の答えとはかけ離れた値を返しました。
タイプをlongに変更したとき、すべてがおかしなドーリーでした。
デフォルトでは、C#整数演算はオーバーフロー時に例外をスローしません。これは、プロジェクト設定を介して、またはchecked
計算を実行することで実現できます。
int result = checked(largeInt + otherLargeInt);
これで操作がスローされます。
反対はunchecked
です。これにより、すべての操作が明示的にオフになります。明らかに、これは、プロジェクト設定でチェックされた操作を有効にしている場合にのみ意味があります。
C#では OverflowException
はスローされません(VBではデフォルトで例外がスローされます)。
例外を取得するには、コードをchecked
コンテキストに埋め込む必要があります。
byte value = 241;
checked
{
try
{
sbyte newValue = (sbyte) value;
Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.",
value.GetType().Name, value,
newValue.GetType().Name, newValue);
}
catch (OverflowException)
{
Console.WriteLine("Exception: {0} > {1}.", value, SByte.MaxValue);
}
}
MSDNはさらに詳しく説明します。
算術演算、キャスト演算、または変換演算でOverflowExceptionをスローするには、チェックされたコンテキストで演算が発生する必要があります。デフォルトでは、Visual Basicの算術演算とオーバーフローがチェックされます。 C#ではそうではありません。チェックされていないコンテキストで操作が発生した場合、結果は、宛先タイプに適合しない上位ビットを破棄することにより切り捨てられます。
これは、デフォルトでは、C#が整数オーバーフローとアンダーフローの例外をスローしないためです。ここでできることはいくつかあります。
オプション1
[プロジェクト] => [プロパティ] => [ビルド]タブ=> [詳細] =>算術オーバーフローアンダーフローを確認して、例外をスローできるようにする必要があります(オプションにチェックを入れてください)。
オプションにチェックを入れてください
オプション2
チェックされたブロックを使用し、オーバーフロー例外をスローして状況を処理します。サンプルコードスニペットは
try
{
checked
{
int y = 1000000000;
short x = (short)y;
}
}
catch (OverflowException ex)
{
MessageBox.Show("Overflow");
}
catch (Exception ex)
{
MessageBox.Show("Error");
}
これがあなたを助けることを願っています... :)
私はすでにcmtを追加しましたが、一部の人にとっては興味深いかもしれません。
msdn は次のことを示しています。
整数演算オーバーフローは、OverflowExceptionをスローするか、結果の最上位ビットを破棄します
だが
10進算術オーバーフローは、常にOverflowExceptionをスローします。
また
整数オーバーフローが発生する場合、何が起こるかは実行コンテキストに依存し、実行コンテキストはチェックまたはチェック解除できます。チェックされたコンテキストでは、OverflowExceptionがスローされます。チェックされていないコンテキストでは、結果の最上位ビットが破棄され、実行が続行されます。したがって、C#では、オーバーフローを処理するか無視するかを選択できます。
デフォルトでは、C#は整数の算術オーバーフローをチェックしません。これを変更するには、/checked
コンパイラオプション を使用するか、Visual Studioで[算術オーバーフロー/アンダーフローのチェック]を有効にします(プロジェクトプロパティ-ビルド-詳細)。
checked
およびunchecked
キーワード を使用して、デフォルトを個別にオーバーライドできます。コードの一部で行われるチェックに依存している場合は、checked
を使用して明示的に有効にすることをお勧めします。
int j = checked(i * 2);
checked
{
int j = i * 2;
// Do more stuff
}
浮動小数点演算ではOverflowException
がスローされず、10進演算では常にOverflowException
がスローされることに注意してください。 C#演算子 も参照してください。