2013-09-26 43 views
2

为什么这段代码http://ideone.com/YRcICG为什么Convert.ToInt32(1.0/0.00004)!=(Int32)已(1.0/0.00004)

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)); 
} 

结果

假24999,000000000 25000,000000000

在CLR的情况下

/C#实现

+1

'0.00004'不可表示 –

回答

5

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

(1.0/a)= 24999.99999999999636202119290828704833984375。

当你使用CAST你只有这个数字的第一部分,而转换方法以不同的方式工作,这里是转换方法的代码:

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")); 
} 

正如你可以看到有一个if语句,用于检查铸造值与原始双倍之间的差异,在您的示例中为:

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

24999.99999999999636202119290828704833984375 - 24999 > 0.5 

,因此您会获得增量。

+0

这回答了这个问题。 – Silvermind

0

浮点数学不准确。像0.2这样的简单值不能用二进制浮点数精确表示,并且浮点数的有限精度意味着操作顺序的轻微变化可能会改变结果。 A必须读:由零,无效操作和不精确溢,下溢,除法:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

IEEE标准划分异常转换成5类。每类异常都有一个单独的状态标志。前三个例外的含义是不言而喻的。无效操作涵盖表D-3中列出的情况以及涉及NaN的任何比较。

+0

只是一个问题,但该文件是否覆盖了转换和转换之间的区别,因为它是一个相当长的文档。 – Silvermind

+0

你能提供更多关于CLR实现的细节吗? – diimdeep

+0

你读过这个问题了吗?因为我不确定代码是否与精度有关。这是关于'转换' – Silvermind

1

角色中继线浮点数

(Int32)已41.548 == 41

转换轮的数目(功能?)

Convert.ToInt32(41.548) == 42

+3

的区别它不是一个功能,它是完全记录的行为(请参阅[相关问题](http://stackoverflow.com/a/10754283/1166450) )) –

+0

这不能解释为什么((int)(1.0 /(1.0/25000)))== 24999 – diimdeep

+1

@diimdeep,因为'1.0/0.0004 == 24999.999999999996'。我编辑了我以前的评论,查看相关问题。 –

3

在您的计算中,1.0/0.00004的答案正在转换为略小于2500的值,因为浮点数不能精确地表示所有可能的值。鉴于此,

为什么这两个整数有不同的值?

将一个double投射到一个int truncates the value,所以小数点后面的所有内容都将被丢弃。

Convert.ToInt32rounds to the nearest integer

为什么浮点数不精确?

见另一个答案链接的优秀文章:What Every Computer Scientist Should Know About Floating-Point Arithmetic

我怎么能代表值精确?

您可以使用十进制类型而不是双倍。有这样做的优点和缺点,请参阅decimal vs double! - Which one should I use and when?

相关问题