ダブルからintに変換するための最良の(最も安全な)方法
-
30-09-2019 - |
質問
ダブルをINTに変換する最良の方法については興味があります。ランタイムの安全性はここでの私の主な関心事です(必ずしも最速の方法である必要はありませんが、それは私の二次的な懸念です)。以下に思いつくことができるいくつかのオプションを残しました。誰もがベストプラクティスであるかどうかを検討できますか?私がリストしていないこれを達成するためのより良い方法はありますか?
double foo = 1;
int bar;
// Option 1
bool parsed = Int32.TryParse(foo.ToString(), out bar);
if (parsed)
{
//...
}
// Option 2
bar = Convert.ToInt32(foo);
// Option 3
if (foo < Int32.MaxValue && foo > Int32.MinValue) { bar = (Int32)foo; }
解決
あなたの最良の選択肢はすることだと思います:
checked
{
try
{
int bar = (int)foo;
}
catch (OverflowException)
{
...
}
}
から 明示的な数値変換テーブル
ダブルまたはフロート値から積分タイプに変換すると、値は切り捨てられます。結果の積分値が宛先値の範囲外である場合、結果はオーバーフローチェックコンテキストに依存します。チェックされたコンテキストでは、オーバーフローエクセプションがスローされますが、未確認のコンテキストでは、結果は宛先タイプの不特定の値です。
ノート: オプション2 また、スローします OverflowException
必要な場合に。
他のヒント
オプション2が好きです。
あなたがする必要があることの1つは、オプション1で「解析」をチェックしているのと同じ方法で、それが機能したことを確認するために例外を確認することです。
try
{
bar = Convert.ToInt32(foo);
}
catch(OverflowException)
{
// no can do!
{
二重の代わりに文字列などを変換している場合、代わりに「formatexception」が得られる場合があります。
編集
私はもともと、オプション2はオプション1よりも特に優れていないと言っていましたが、 @0xa3は間違っていると指摘しました。オプション1は、整数に解析される前に文字列に変換するため、さらに悪いことです。つまり、効率が低下します。また、ダブルが整数範囲の外側にある場合(あなたが望んでいるかもしれないし、そうでないかもしれない)、オーバーフローエクセプトは得られませんが、この場合は「解析」は偽です。
これはOPが求めていたものではないことを理解していますが、この情報は便利かもしれません。
ここに比較があります(から http://www.dotnetspider.com/resources/1812-difference-among-int-parse convert-toint.aspx)
string s1 = "1234";
string s2 = "1234.65";
string s3 = null;
string s4 = "12345678901234567890123456789012345678901234567890";
int result;
bool success;
result = Int32.Parse(s1); // 1234
result = Int32.Parse(s2); // FormatException
result = Int32.Parse(s3); // ArgumentNullException
result = Int32.Parse(s4); // OverflowException
result = Convert.ToInt32(s1); // 1234
result = Convert.ToInt32(s2); // FormatException
result = Convert.ToInt32(s3); // 0
result = Convert.ToInt32(s4); // OverflowException
success = Int32.TryParse(s1, out result); // 1234
success = Int32.TryParse(s2, out result); // 0
success = Int32.TryParse(s3, out result); // 0
success = Int32.TryParse(s4, out result); // 0
オプション3A例外を使用していない場合、常に値を返します。
Int32 Convert(Double d)
{
if (d <= (double)Int32.MinValue)
return Int32.MinValue;
else if (d >= (double)Int32.MaxValue)
return Int32.MaxValue;
else
return (Int32)d;
}
私は常にConvertクラスを使用しています。非常にエレガントで便利で、VS Intellisenseで定義されている特定の例外をキャッチできます。
オプション2を使用します。短く、きれいで、それは機能します。
.NET4のBigIntegerクラスを調べることもできます。オーバーフローを確認する必要はありません。
double foo = 1;
BigInteger bigint = new BigInteger(foo);
何かがうまくいかなかったかどうかを本当に確認する必要がある場合は、通常のキャストを使用して結果を確認してください。
int ToInt(double foo)
{
int result = (int)foo;
if (foo != result)
throw new ArgumentException()
return result;
}
これにより、無効な変換が行われないようになります。最寄りの整数に丸めても大丈夫なら、使用してください Math.Round
結果が0.5以内であるかどうかを確認します。これにより、NANまたはInfinityがメソッドによって得られないことを確認します。
オプション(1)および(2)は本質的に同じことを行います。オプション(1)はあなたに与えます if (parsed)
オプション(2)が任意のエラーをスローするのに対してブロック double
それは次のように表現できません int
.
オプション(3)は、追加のオプション(2)と本質的に同じです MinValue
/MaxValue
他の人がいないものを確認してください。
要約すると、これらの3つのコードが異なることを行います。オプション(3)は、追加の範囲チェックがあるという点で、最も堅牢であるように見えます。
編集: 考え直して、@aniを使用してください checked
トリック - レンジチェックを無料で取得します。