为何选择Convert.ToInt32(1.0/0.00004)!=(Int32)(1.0/0.00004)

dii*_*eep 2 c# math clr casting .net-4.0

为什么这个代码 http://ideone.com/YRcICG

void Main()
{   
    double a = 0.00004;
    Int32 castToInt = (Int32)(1.0/a);
    Int32 convertToInt = Convert.ToInt32(1.0/a);

    Console.WriteLine("{0} {1:F9} {2:F9}", castToInt == convertToInt, castToInt, convertToInt);

    Console.WriteLine((((int)(1.0/(1.0/25000))) == 24999));
}
Run Code Online (Sandbox Code Playgroud)

结果是

错24999,000000000 25000,000000000

在CLR/C#实现的上下文中

Ale*_*iuc 5

诀窍在于double的表示方式,因此(1.0/a)将以下列方式表示:

(1.0/a)= 24999.99999999999636202119290828704833984375.

当你使用cast时你只得到这个数字的第一部分,而convert方法的工作方式不同,这里是Convert方法的代码:

public static int ToInt32(double value)
{
    if (value >= 0.0)
    {
        if (value < 2147483647.5)
        {
            int num = (int)value;
            double num2 = value - (double)num;
            if (num2 > 0.5 || (num2 == 0.5 && (num & 1) != 0))
            {
                num++;
            }
            return num;
        }
    }
    else
    {
        if (value >= -2147483648.5)
        {
            int num3 = (int)value;
            double num4 = value - (double)num3;
            if (num4 < -0.5 || (num4 == -0.5 && (num3 & 1) != 0))
            {
                num3--;
            }
            return num3;
        }
    }
    throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,有一个if语句可以检查已转换值和原始double之间的区别,在您的示例中它是:

int num = (int)value;
double num2 = value - (double)num;

24999.99999999999636202119290828704833984375 - 24999 > 0.5
Run Code Online (Sandbox Code Playgroud)

因此你得到了增量.