我想了解为什么 POSITIVE_INFINITY
和 NEGATIVE_INFINITY
常量仅针对 float 据类型定义(float
、double
和它们的包装器),
public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
但不适用于整数数据类型(byte
、short
、int
、long
及其包装器)。这会影响不同数据类型的除法运算结果。例如:
对于整数类型:
int z = 10/0;
System.out.println(z);
Output:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at TesterClass.main(TesterClass.java:16)
对于浮点类型:
double z = 10/0.0;
System.out.println(z);
Output:
Infinity
Java 中的整数类型使用无符号二进制(对于 char
)或二进制补码符号表示。在这两种表示法中都没有“无穷大”的表示法。例如,int
有 2^32 个可能的值,它们都表示有限的数字。
(Integer.MIN_VALUE
是 -231,Integer.MAX_VALUE
是 231 - 1,并且如果你把它们都算上……包括零……那就是 232 个不同的值。)
相比之下, float 是使用 IEEE 二进制浮点表示法表示的,并且这些确实具有表示无穷大值和非数字值的标准方法。
因此,为浮点类型定义POSITIVE_INFINITY
和NEGATIVE_INFINITY
常量是有意义的,而不可能为整数类型。
如果你想知道为什么会这样:
设计/选择整数表示(很久以前!)以最大限度地提高速度。任何特殊情况(比如为表示无穷大而保留的值等)都会使整数运算硬件更加复杂和缓慢。如果硬件设计者的目标是在一个时钟周期内进行整数加法,那么使加法更复杂意味着时钟速度必须更慢。这会影响整个处理器的速度。
另一方面是:
- 在没有任何明确通知的情况下发生溢出(这可能是可取的,也可能不是可取的)
- 被零除必须通过硬件异常处理,这会导致严重的性能损失......如果它真的发生了。
设计 IEEE 浮点表示的标准委员会还考虑了需要能够表示无穷大的科学和工程领域的要求。由于需要进行缩放等,浮点运算已经变得更慢和更复杂。因此它们很可能已经是多周期指令,并且可能有一些“松弛”来处理特殊情况。
此外,还有一个优点是:INF 和 NaN 值允许创建它们的操作在没有硬件异常的情况下继续进行,但不会像整数溢出那样“将不良操作扫到地毯下” .
请注意,1949 年一台工作计算机 (EDSAC) 中使用了二进制补码。 IEEE 754 标准出现于 1985 年。
就其值(value)而言,一些编程语言知道整数溢出;例如艾达。但是他们不会用无穷大等表示来做到这一点。相反,当操作溢出时,他们会抛出一个异常(或等效的)。即便如此,这也会增加性能损失,因为溢出检测通常需要在每个整数算术指令之后执行额外的指令来测试“溢出”状态位。 (这就是现代指令集的工作方式......)