这个问题在这里已有答案:
我想了解为什么POSITIVE_INFINITY
和NEGATIVE_INFINITY
常量只定义为浮点数据类型(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个不同的值。)
相比之下,使用IEEE二进制浮点表示来表示浮点数,并且这些数字确实具有表示无穷大和非数字值的标准方式。
因此,为浮点类型定义POSITIVE_INFINITY
和NEGATIVE_INFINITY
常量是有意义的,并且不可能为整数类型定义它们。
如果你想知道为什么会这样:
请注意,1949年(EDSAC)在工作计算机中使用了两个补码。 IEEE 754标准于1985年出现。
对于它的价值,一些编程语言意识到整数溢出;例如阿达。但是他们不会用无穷大的表示等来做这件事。相反,当操作溢出时,它们会抛出异常(或等效的)。即便如此,这也增加了性能损失,因为溢出检测通常需要在每个整数算术指令之后的额外指令来测试“溢出”状态位。 (这就是现代教学设定的方式......)
它是IEEE 754浮点标准的一部分,如this spec中所述:
浮点类型是
float
和double
,它们在概念上与单精度32位和双精度64位格式IEEE 754值和操作相关联,如IEEE标准二进制浮点运算,ANSI / IEEE标准754-1985(IEEE,纽约)。IEEE 754标准不仅包括由符号和幅度组成的正数和负数,还包括正和负零,正和负无穷大以及特殊的非数字值(以下简称为NaN)。
这些特殊值是根据标准的位表示计算的。例如,基于Double
位表示计算0x7ff0000000000000
正无穷大。
相反,整数类型没有无限值的位表示。它们只有有限数的表示。 Integer
类将最小和最大有限值定义为-231和231-1。
正如其他人所指出的,它是在IEEE规范等中。浮点数和双精度数支持NaN和Infinity,而整数则不支持。
就其背后的推理而言,没有任何东西可以被零整除,而对于整数,你知道你试图除以零。
浮点数不准确。 0.003f - 0.001f - 0.002f在数学上为零,但根据IEEE规范和我们在计算机中表示数字的能力,它是-2.3283064E-10。您可以用二进制表示有限数量的十进制数,并且没有任何表示可以让我们始终获得零的正确值。
如果tinyFloat ==(0.003f - 0.001f - 0.002f)== -2.3283064E-10
这在数学上为零,几乎为零,但是1f / tinyFloat == -4.2949673E9
// This still works too:
scala> Integer.MAX_VALUE / (tinyFloat * tinyFloat * tinyFloat)
res58: Float = -1.7014118E38
// But eventually you overflow
scala> Integer.MAX_VALUE / (tinyFloat * tinyFloat * tinyFloat * tinyFloat)
res59: Float = Infinity
(如果您不熟悉,Scala是一种JVM语言,因此上述值类型与Java相同。)
最后一个tinyFloat ^ 4仍然不完全为零,因此计算机抛出ArithmeticException没有意义。整数不存在此问题。没有其他方法可以溢出分裂。 Integer.MAX_VALUE / 1仍为Integer.MAX_VALUE。你要么除以零,这在数学上是无效的,可用二进制表示,或者你没有,并得到了有效的结果。
数学上,1/0 = Infinity
因为我们认为除以零作为limit(x -> 0) 1/x
,而且隐含的理解x
是一个正数量。浮点除法必须支持小数除法,并且假设操作在语义上有一个小的误差范围,并且假设该操作可能包括0,那么由于四舍五入导致由于小数量的除法而引发异常完全等于0是完全不合适的。
除以整数零除以实际上是未定义的。如果你除以整数零,你可能不应该。当然,做这些额外的事情会严重影响性能。
为了比较,Integer支持Integer.MAX/MIN_VALUE
。这些不应该由于操作而产生,而是用于像int minSoFar = Integer.MAX_VALUE;
之类的步骤的算法。