17

double を 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; }
4

8 に答える 8

28

あなたの最善の選択肢は次のことだと思います:

checked
{
    try
    {
        int bar = (int)foo;
    }
    catch (OverflowException)
    {
     ...          
    }
}

明示的な数値変換テーブルから

double または float 値から整数型に変換すると、値が切り捨てられます。結果の整数値が宛先値の範囲外である場合、結果はオーバーフロー チェック コンテキストに依存します。チェックされたコンテキストでは、OverflowException がスローされますが、チェックされていないコンテキストでは、結果は宛先タイプの未指定の値になります。

注:オプション 2は、必要に応じて もスローしOverflowExceptionます。

于 2010-08-23T15:51:29.977 に答える
6

私はオプション2を好みます。

オプション1で「解析済み」をチェックしているのと同じ方法で、それが機能していることを確認するために、例外をチェックする必要があります。

try
{
    bar = Convert.ToInt32(foo); 
}
catch(OverflowException)
{
    // no can do!
{

double ではなく string などを変換していた場合、代わりに「FormatException」が発生する可能性があります。

編集

私は当初、オプション 2 はオプション 1 より特に優れているわけではないと言いましたが、@0xA3 はそれが間違っていると指摘しました。オプション 1 は、整数に解析される前に文字列に変換されるため、効率が低下します。また、double が整数の範囲外にある場合 (必要な場合とそうでない場合があります)、OverflowException は発生しません。ただし、この場合、「解析済み」は False になります。

于 2010-08-23T15:53:05.550 に答える
5

これは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
于 2010-08-23T15:58:49.937 に答える
4

オプション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;
    }
于 2010-08-23T16:08:07.753 に答える
2

私は常に Convert クラスを使用しています。非常にエレガントで便利で、VS インテリセンスで定義された特定の例外をキャッチできます。

于 2010-08-23T15:54:20.810 に答える
2

オプション2を使用します。短く、きれいで、うまくいきます。

.Net4 の BigInteger クラスを調べることもできます。オーバーフローをチェックする必要はありません。

double foo = 1;            
BigInteger bigint = new BigInteger(foo);
于 2010-08-23T15:44:04.603 に答える
1

オプション(1)と(2)は基本的に同じことをします。オプション(1)はブロックを提供しますが、オプション(2)は、として表現できないものif (parsed)に対してエラーをスローします。doubleint

オプション(3)は、オプション(2)と基本的に同じですが、他のオプションにはない追加のMinValue/MaxValueチェックがあります。

要約すると、これら3つのコードは異なることを行います。オプション(3)は、追加の範囲チェックがあるという点で、最も堅牢であるように見えます。

編集:考え直して、@Anicheckedトリックを使用してください-あなたは無料で範囲チェックを取得します。

于 2010-08-23T15:50:45.477 に答える
1

本当に何かがうまくいかなかったかどうかを調べる必要がある場合は、通常のキャストを使用して結果を確認してください。

int ToInt(double foo)
{
    int result = (int)foo;
    if (foo != result)
        throw new ArgumentException()

    return result;
}

これにより、無効な変換が行われないようになります。最も近い整数に丸めても問題ない場合は、を使用Math.Roundして、結果が0.5以内かどうかを確認します。これにより、NaNまたは無限大がメソッドによって取得されないことが保証されます。

于 2010-08-23T15:51:14.150 に答える