1

確認してください: この小さな .NET コンソール プログラムは興味深い結果をもたらします... 2 つの異なる方法で浮動小数点数を整数に変換する方法に注目してください。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CastVsConvert
{
    class Program
    {
        static void Main(string[] args)
        {
            int newWidth = 0;
            CalculateResizeSizes(600, 500, out newWidth);
        }

        static void CalculateResizeSizes(int originalWidth, int maxWidth, out int newWidth)
        {
            float percentage = 1.0F;
            percentage = maxWidth / (float)originalWidth;

            newWidth = (int)((float)originalWidth * percentage);
            int newWidthConvert = Convert.ToInt32((float)originalWidth * percentage);

            Console.Write("Percentage: {0}\n", percentage.ToString());
            Console.Write("Cast: {0}\n", newWidth.ToString());
            Console.Write("Convert: {0}\n", newWidthConvert.ToString());
        }
    }
}

「Cast」と「Convert」の出力は同じになると思いますが、そうではありません...出力は次のとおりです。

C:\Documents and Settings\Scott\My Documents\Visual Studio 2008\Projects\CastVsC
onvert\CastVsConvert\bin\Debug>CastVsConvert.exe
Percentage: 0.8333333
Cast: 499
Convert: 500

ここで.NETが異なる値を返す理由を知っている人はいますか?

4

4 に答える 4

14

それはバグではなく、cast切り捨てられ、convert丸められます。

これを見る

于 2008-11-03T20:49:20.857 に答える
5

キャストは、変換が丸められている間、小数点以下の数値の部分を切り取っています。

于 2008-11-03T20:48:59.720 に答える
5

Convert.ToInt32の戻り値のドキュメントから:

最も近い 32 ビットの符号付き整数に丸められた値。値が 2 つの整数の中間にある場合、偶数が返されます。つまり、4.5 は 4 に変換され、5.5 は 6 に変換されます。

キャストは切り上げられません。切り捨てられるだけです。乗算の結果は 500 をわずかに下回るため、キャストによって 499 に切り捨てられますが、Convert.ToInt32 では 500 に切り上げられます。

于 2008-11-03T20:49:42.963 に答える
1

おそらくこれを引き起こしている余分な隠されたキャストがあります。たとえば、再計算の代わりにこれを使用する場合:

int newWidthConvert = Convert.ToInt32(newWidth);

同じ結果が得られます。Reflector を使用して をのぞくと、何が起こっているかがより明確になりますConvert.ToInt32(float)

public static int ToInt32(float value)
{
    return ToInt32((double) value);
}

への隠しキャストがありDoubleます。

調査するために数行を追加してから、デバッガーを使用して確認すると、何が起こるかがわかります。

float newWidth1 = ((float)originalWidth * percentage);
double newWidth2 = ((float)originalWidth * percentage); 

doubleはより正確で、値を 499.999999 とさらに数桁として保存します。 floatは精度が低く、500.0 が格納されます。整数変換では小数部分が切り捨てられるため、中間キャストに基づいて 500 または 499 になります。を呼び出すConvert.ToInt32()と、結果はすでに にキャストされているため、500.0floatの表現が得られます。Double個人的には、できる限り常に使用doubleすることを好みます。

于 2008-11-03T20:59:04.457 に答える