【问题标题】:Differences in Overflow Semantics Between C# and JavaC# 和 Java 之间溢出语义的差异
【发布时间】:2013-08-22 20:25:21
【问题描述】:

获取以下代码:

const float fValue = 5.5f;
const float globalMin = 0.0f;
const float globalMax = 5.0f;
float vFactor = (float)(2e9 / (globalMax - globalMin));
int iValue = (int)((fValue - globalMin) * vFactor); 

最后一行导致一个溢出int 的值。在 C# 中,结果未指定:

  • 6.2.1 显式数字转换
  • 对于从 float 或 double 到整数类型的转换,处理取决于发生转换的溢出检查上下文(第 7.6.12 节):
    • 在未经检查的上下文中,转换始终成功,并按如下方式进行。
      • 如果操作数的值为 NaN 或无穷大,则转换的结果是目标类型的未指定值。
      • 否则,源操作数将向零舍入到最接近的整数值。如果这个整数值在目标类型的范围内,那么这个值就是转换的结果。
      • 否则,转换的结果是目标类型的未指定值。

在java中...好吧,我不知道,这就是我在这里的原因。我知道如何处理典型的整数溢出(即Integer.MAX_VALUE + 1),但我在规范中找不到任何将溢出作为float 转换结果的内容。

在我的测试 (Java) 中,最后一行的结果是 Integer.MAX_VALUE,它告诉我还有更多事情发生,因为如果值简单地翻转,我预计它会是 -2094967296。看起来 Java 在溢出时被截断为 MAX_VALUE

编辑:感谢@Pascal Cuoq 指出将浮点数截断为 int 的 SSE2 汇编指令会在溢出时产生 INT_MIN。我将修复 C# 端的错误,但我仍然对 Java 指定此行为的位置/是否指定感到好奇。

【问题讨论】:

  • I may even have to emulate this bug - 完全史诗。
  • @HighCore:是的……我刚刚和我的老板谈过了……这不会发生。我会修复它并记录它,但我仍然想知道这是否在 Java 领域中指定。
  • 您可能有兴趣听到将浮点数截断为 int 的 SSE2 汇编指令在溢出时产生 INT_MIN(正数和负数)。您在 C# 中看到的是汇编指令的直接结果。然而,这只是英特尔的选择,并没有什么特别的意义。 Java 有更多“定义一切”的态度(它来自一家当时正在设计自己的非英特尔处理器的公司),所以我推测他们一定是强制实现为正溢出产生 INT_MAX。
  • I'm converting a bunch of Java code to C#你试过IKVM
  • @PascalCuoq:这是有道理的。谢谢。

标签: c# java integer-overflow


【解决方案1】:

Java 语言规范中明确定义了数据类型之间的转换(请参阅Conversions and Promotions 部分)。

我相信您的案例属于5.1.3. Narrowing Primitive Conversion,您可以在其中看到:

  • 首先,您的浮点数将使用 IEEE 754 向零舍入模式舍入为整数(解释为 here)和
  • 将根据值是太小还是太大,为其分配最大或最小的可表示整数值。

【讨论】:

  • 啊,我错过了!谢谢。这就解释了。
猜你喜欢
  • 1970-01-01
  • 2022-01-03
  • 2016-05-14
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2021-04-16
  • 2012-11-14
  • 1970-01-01
相关资源
最近更新 更多