为什么(int)(1.0 / x),其中x = 0会导致In32.MinValue而不是Int32.MaxValue?

时间:2014-01-28 21:40:13

标签: c# java integer-overflow

在Java中,

int x = 0;
(int)(-1.0 / x) -> Integer.MinValue
(int)(1.0 / x) -> Integer.MaxValue

但是在C#中,

int x = 0;
(int)(-1.0 / x) -> Int32.MinValue
(int)(1.0 / x) -> Int32.MinValue!!

如果"未选中"行为将是相同的。使用语句/运算符,如果"检查"而是使用它然后它是一个溢出异常。

但可以肯定的是,在未经检查的上下文中,除了1.0 / x(其中x = 0)之外,还会产生Int32.MaxValue,而不是Int32.MinValue。

我错过了什么吗?

2 个答案:

答案 0 :(得分:10)

真的,不应该期待任何东西。从C#规范,第6.2.1节(强调我的):

  

floatdouble转换为整数类型[...]。    - 在未经检查的上下文中,转换始终成功,并按如下方式进行。      - 如果操作数的值为NaN或无穷大,则转换结果为目标类型的未指定值

将其与Java规范进行比较,section 5.1.3

  

将浮点数转换为整数类型T需要两个步骤:

     

在第一步中,浮点数转换为long(如果T为long)或转换为int(如果T为byte,short,char或int),如下所示:

     
      
  • 如果浮点数为NaN(§4.2.3)[...],则转换的第一步结果为int或long 0。
  •   
  • 否则,如果浮点数不是无穷大[...]
  •   
  • 否则,以下两种情况之一必须为真:   
        
    • 该值必须太小(大幅度或负无穷大的负值),第一步的结果是int或long类型的最小可表示值。
    •   
    • 值必须太大(大幅度或正无穷大的正值),第一步的结果是int或long类型的最大可表示值。
    •   
  •   

基本上,这两种语言有不同的保证,实现似乎都能满足这些保证。

我认为因为更宽松的规范,.NET JIT能够使用更高效的转换,这恰好会导致int.MinValue

答案 1 :(得分:7)

C#中的行为未定义。引自C# Language Specification(和this answer):

  

对于从float或double到整数类型的转换,处理取决于发生转换的溢出检查上下文(第7.6.12节)。在未选中的上下文中:如果操作数的值为NaN或无穷大,则转换的结果是目标类型的未指定值。