将NaN强制转换为int时,为什么值会根据是否分配给变量而更改?

时间:2017-03-01 16:27:04

标签: c#

将double.NaN转换为int将为0。

Console.WriteLine(unchecked((int)double.NaN));    // 0

但是,将double.NaN指定给变量然后转换为int将为-2147483648。

double value = double.NaN;
Console.WriteLine (unchecked ((int) value));    // -2147483648
Console.WriteLine ((int) value);                // -2147483648

为什么结果会根据是否将其分配给变量而改变?

C#规范

6.2.1显式数字转换

  • 在已检查的上下文中,转换过程如下:
    • 如果操作数的值为NaN或无限,则抛出System.OverflowException。
    • 否则,源操作数向零舍入为最接近的整数值。如果此整数值在目标类型的范围内,则此值是转换的结果。
    • 否则,抛出System.OverflowException。
  • 在未选中的上下文中,转换始终成功,并按如下方式进行。
    • 如果操作数的值为NaN或无限,则转换结果为目标类型的未指定值。
    • 否则,源操作数向零舍入为最接近的整数值。如果此整数值在目标类型的范围内,则此值是转换的结果。
    • 否则,转换结果是目标类型的未指定值。

管环境

  • 编译器:Visual Studio 2013
  • Rimtime:.NET Framework 4.6.0
  • 操作系统:Windows 10版本1607
  • CPU:Intel Core i7 920

视窗:

Console.WriteLine(Environment.OSVersion);    // Microsoft Windows NT 6.2.9200.0
Console.WriteLine(Environment.Version);      // 4.0.30319.42000

2 个答案:

答案 0 :(得分:3)

默认情况下,控制台应用程序编译为unchecked。那么你的最后一个例子显示的值与明确使用unchecked的例子相同。

对于其余示例,您引用的规范部分适用:

  
      
  • 在未选中的上下文中,转换始终成功,并按如下方式进行。      
        
    • 如果操作数的值为NaN或无限,则转换结果为目标类型的未指定值
    •   
  •   

(由我强调)。

未指定表示您不能依赖结果。它可以是0-2147483648或其他任何内容。

我想弄清楚在你的特殊情况下会发生什么,但是我得到-2147483648两种方式。因此很难追查。

答案 1 :(得分:1)

环顾四周后,我想我得到了这里发生的事情。你没有投0,你正在施放NaN。 intInt32的范围小于double。我认为这些令人愉快的不太明确的规则正在共同导致差异:

  
      
  • 如果操作数的值为NaN或无穷大,则转换的结果是目标类型的未指定值。   否则,源操作数向零舍入为最接近的整数值。
  •   
  • 如果此整数值在目标类型的范围内,则此值是转换的结果。
  •   

此处的目的地类型是较小的int,值为" -2147483648"您获得的是32位有符号整数的最小值。这表明转换操作正在将NaN转换为double.NegativeInfinity以便使用它执行操作。最接近double.NegativeInfinity的整数是int.MinValue,这是您获得的值。

所有这些都表明,这个值未指定这一事实意味着您获得的结果可能取决于太多因素,直至您是否分配了变量甚至是什么处理器架构你有。您不应该使用NaN转换来执行任何有意义的操作,因此NaN永远不会被赋予实际的设置值(主要是因为根据定义,它将是一个数字)。出于大多数目的,出于这个原因,应将NaN结果视为错误。实际价值最终毫无意义。