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

J S*_*ith 3 c# java integer-overflow

在Java中

int x = 0;
(int)(-1.0 / x) -> Integer.MinValue
(int)(1.0 / x) -> Integer.MaxValue
Run Code Online (Sandbox Code Playgroud)

但在C#中,

int x = 0;
(int)(-1.0 / x) -> Int32.MinValue
(int)(1.0 / x) -> Int32.MinValue!!
Run Code Online (Sandbox Code Playgroud)

如果使用"unchecked"语句/运算符,行为将是相同的,如果使用"checked",则它是溢出异常.

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

我错过了什么吗?

Jon*_*eet 10

真的,人们不应该期待任何事情.从C#规范,第6.2.1节(强调我的):

用于转换float或转换double为整数类型[...]. - 在未选中的上下文中,转换始终成功,并按如下方式继续.- 如果操作数的值为NaN或无穷大,则转换结果是目标类型的未指定值.

将其与Java规范进行比较,第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结果.


Dou*_*las 7

C#中的行为未定义.引用C#语言规范(和这个答案):

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