C#和Java之间溢出语义的差异
本文关键字:语义 溢出 Java 之间 | 更新日期: 2023-09-27 18:28:38
获取以下代码:
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显式数字转换
- 对于从浮点或双精度到整型的转换,处理取决于进行转换的溢出检查上下文(§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在哪里/是否指定了这种行为。
数据类型之间的转换在Java语言规范中有很好的定义(请参阅转换和升级部分)。
我相信你的案子属于5.1.3。缩小原始转换,您可以看到:
- 首先,您的浮点值将使用IEEE 754向零取整模式(此处解释)取整为整数
- 它将被分配最大或最小的可表示整数值,这取决于该值是太小还是太大