“在这些情况下不抛出异常的理由是什么?这是IEEE标准,还是Java设计者的选择?”
“
IEEE 754-1985标准在第20页和21页的2.2.1 NANs和2.2.2 Infinity章节中清楚地解释了为什么需要标准中的NAN和Infinity值。因此这不是Java的问题。”
“
Java虚拟机规范在第
3.8.1浮点算术和IEEE 754节中指出,在进行到整数类型的转换时,JVM会向零舍入,这解释了您所看到的结果。”
“该标准确实提到了一个名为“陷阱处理程序”的功能,可以用于确定溢出或NAN何时发生,但Java虚拟机规范明确指出,这对于Java来说没有被实现。它在第3.8.1节中说:”
“Java虚拟机的浮点运算不会抛出异常、陷阱或其他信号,也不会发出IEEE 754的无效操作、除以零、溢出、下溢或不精确的异常条件。Java虚拟机没有信号NaN值。”
“因此,无论后果如何,行为都不是未指定的。”
如果使用这种类型转换会发生异常,那么我是否有所不知的坏后果?
理解标准中给出的原因就足以回答这个问题。标准用详尽的例子解释了你在这里问的后果。我可以把它们发布出来,但这会是太多信息,而且这些例子可能无法适当地格式化在此版本工具中。
编辑
我正在阅读最新的Java虚拟机规范维护审核,这是由JCP最近作为JSR 924的一部分发布的,其中第2.11.14节命名为类型转换指令包含了一些更多的信息,这可能有助于您寻找答案,虽然还不是您要寻找的,但我相信它有一点帮助。它说:
在将浮点值转换为整数类型T的缩小数值转换中,其中T为int或long时,浮点值的转换如下:
- 如果浮点值为NaN,则转换的结果为int或long 0。
- 否则,如果浮点值不是无穷大,则使用IEEE 754向零舍入模式将浮点值四舍五入为整数值V。
有两种情况:
- 如果T为long且此整数值可以表示为long,则结果为long值V。
- 如果T为int类型且此整数值可以表示为int,则结果为int值V。
否则:
- 值可能太小(具有较大幅度的负值或负无穷大),结果是类型int或long的最小可表示值。
- 或者值可能太大(具有较大幅度的正值或正无穷大),结果是类型int或long的最大可表示值。
从double到float的缩小数值转换遵循IEEE 754。使用IEEE 754舍入到最近模式正确舍入结果。无法表示为float的值将转换为float类型的正零或负零;无法表示为float的值将转换为正无穷大或负无穷大。双精度NaN始终转换为浮点NaN。
尽管可能会发生溢出、下溢或精度损失,但数值类型之间的缩小转换从不导致Java虚拟机抛出运行时异常(不要与IEEE 754浮点异常混淆)。
我知道这只是重申了您已经知道的内容,但它有一个线索,似乎IEEE标准要求四舍五入到最近的数字。也许在那里您可以找到这种行为的原因。
编辑
有关IEEE标准的2.3.2节“舍入模式”规定:
默认情况下,“舍入”意味着四舍五入至最近的数字。标准要求提供另外三种舍入模式;即向零舍入、向+无穷大舍入和向-无穷大舍入。
当与转换为整数操作一起使用时,向-无穷大舍入会导致转换成为floor函数,而向+无穷大舍入则是ceiling。
舍入模式会影响溢出,因为当向0舍入或向-无穷大舍入生效时,正数溢出会导致默认结果成为可表示的最大数字,而不是+无穷大。
类似地,当向+无穷大或向0舍入生效时,负数溢出将产生最大负数。
然后他们举了一个例子,说明为什么这在区间算术中很有用。不确定是否这是您要找的答案,但它可以丰富您的搜索。