【发布时间】: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