【问题标题】:Why does (int)(1.0 / x) where x = 0 results in In32.MinValue rather than Int32.MaxValue?为什么 (int)(1.0 / x) where x = 0 会导致 In32.MinValue 而不是 Int32.MaxValue?
【发布时间】:2014-01-28 21:40:13
【问题描述】:

在 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!!

如果使用“unchecked”语句/操作符,行为将是相同的,如果使用“checked”,那么它是一个溢出异常。

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

我错过了什么吗?

【问题讨论】:

  • 因为C# 不是Java
  • @Selman22 两者都遵循 IEEE 的 int 操作规范,而不是他们自己的规范
  • (int)(1.0 / x) 给我 Int32.MaxValue。
  • @Tarec 因此 JonSkeet 回答...

标签: c# java integer-overflow


【解决方案1】:

一个人不应该期待任何事情,真的。来自 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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 2017-02-15
      • 2010-09-11
      • 1970-01-01
      • 2010-10-12
      • 2012-01-30
      • 1970-01-01
      相关资源
      最近更新 更多