Double
Double是基本类型double的包装类,学习之前建议阅读【Jdk源码阅读之Float】相信能更加理解Double。
类图
public final class Double extends Number implements Comparable<Double>
通过类图和源码我们可以知道Double是不可被继承的,并且Double类型的实例对象是可以比较的。由于Double继承了Number(这是一个抽象类),所以Double重写了其所有形如xxxValue的方法。
成员变量
public static final double POSITIVE_INFINITY = 1.0 / 0.0; //正无穷
public static final double NEGATIVE_INFINITY = -1.0 / 0.0; //负无穷
public static final double NaN = 0.0d / 0.0; //NaN
public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308 保存 double 类型的最大正有限值的常量
public static final double MIN_NORMAL = 0x1.0p-1022; // 2.2250738585072014E-308 保存 double 类型的最小正标准值的常量
public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324 保存 double 类型的最小正非零值的常量
public static final int MAX_EXPONENT = 1023; //有限 double 变量可能具有的最大指数。
public static final int MIN_EXPONENT = -1022; //标准化 double 变量可能具有的最小指数
public static final int SIZE = 64; //64位
public static final int BYTES = SIZE / Byte.SIZE; //8字节
public static final Class<Double> TYPE = (Class<Double>) Class.getPrimitiveClass("double");
private final double value;
Double对象的值保持在value中,并且value是不可变的。
构造方法
public Double(double value) {
this.value = value;
}
public Double(String s) throws NumberFormatException {
value = parseDouble(s);
}
public static double parseDouble(String s) throws NumberFormatException {
return FloatingDecimal.parseDouble(s);
}
Double有两个构造方法,可传入double,String类型的值,其中String会借助FloatingDecimal的parseDouble方法进行转换。我们可以传入"NaN","Infinity","0x"开头的十六进制串,科学计数法表示的字符串。
valueOf
public static Double valueOf(String s) throws NumberFormatException {
return new Double(parseDouble(s));
}
public static Double valueOf(double d) {
return new Double(d);
}
valueOf
与构造方法传递参数一样。与Byte,Integer等包装类的valueOf可从缓存中获取-128~127范围内的对象不同,Double调用valueOf都是new实例。
xxxValue
public byte byteValue() {
return (byte)value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return (int)value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return value;
}
这六个方法都是继承自Number类,将value值强转为对应的类型。
toString
public String toString() {
return toString(value);
}
public static String toString(double d) {
return FloatingDecimal.toJavaFormatString(d);
}
返回d的字符串表示。如果d是NaN,返回"NaN";如果d是负数则以'-'为起始标识,正数无标识;如果d是infinity,正数返回Infinity,负数返回-Infinity;如果d是0.0,-0.0返回"-0.0",0.0返回"0.0";如果d<10^-3或d>=10^7则使用科学计数法表示。
toHexString
方法有点长,这里不展示了,此方法返回 double 参数的十六进制字符串表示形式。
- 如果参数为 NaN,那么结果为字符串 "NaN"。
否则,结果是表示参数符号和数值的字符串。如果符号为负,那么结果的第一个字符是 '-' ('u002D');如果符号为正,那么结果中不显示符号字符。对于数值 m:
- 如果 m 为无穷大,则用字符串 "Infinity" 表示;因此,正无穷大生成结果 "Infinity",负无穷大生成结果 "-Infinity"。
- 如果 m 为 0,则用字符串 "0x0.0p0" 表示;因此,负 0 生成结果 "-0x0.0p0",正 0 生成结果 "0x0.0p0"。
- 如果 m 是具有标准化表示形式的 double 值,则使用子字符串表示有效数字和指数字段。有效数字用字符 "0x1." 表示,后跟该有效数字剩余小数部分的小写十六进制表示形式。除非所有位数都为 0,否则移除十六进制表示中的尾部 0,在所有位数都为零的情况下,可以用一个 0 表示。接下来用 "p" 表示指数,后跟无偏指数的十进制字符串,该值与通过对指数值调用 Integer.toString 生成的值相同。
- 如果 m 是非标准表示形式的 double 值,则用字符 "0x0." 表示有效数字,后跟该有效数字剩余小数部分的十六进制表示形式。移除十六进制表示中的尾部 0。然后用 "p-1022" 表示指数。注意,在非标准有效数字中,必须至少有一个非 0 数字。
浮点值 | 十六进制字符串 |
1.0 | 0x1.0p0 |
-1.0 | -0x1.0p0 |
2.0 | 0x1.0p1 |
3.0 | 0x1.8p1 |
0.5 | 0x1.0p-1 |
0.25 | 0x1.0p-2 |
Double.MAX_VALUE | 0x1.fffffffffffffp1023 |
Minimum Normal Value | 0x1.0p-1022 |
Maximum Subnormal Value | 0x0.fffffffffffffp-1022 |
Double.MIN_VALUE | 0x0.0000000000001p-1022 |
isXXX
public boolean isNaN() {
return isNaN(value);
}
public static boolean isNaN(double v) {
return (v != v);
}
public boolean isInfinite() {
return isInfinite(value);
}
public static boolean isInfinite(double v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}
public static boolean isFinite(double d) {
return Math.abs(d) <= DoubleConsts.MAX_VALUE;
}
public static boolean isFinite(double d) {
return Math.abs(d) <= DoubleConsts.MAX_VALUE;
}
通过isNaN方法我们可以了解到Double.NaN != Double.NaN。Java 提供的任何 IEEE 754 浮点操作都不能区分具有不同位模式的两个同类型 NaN 值。不同的 NaN 值只能使用 Double.doubleToRawLongBits 方法区分。
max/min
public static double max(double a, double b) {
return Math.max(a, b);
}
public static double min(double a, double b) {
return Math.min(a, b);
}
hashCode
public int hashCode() {
return Double.hashCode(value);
}
public static int hashCode(double value) {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
/**
* 根据 IEEE 754 浮点双精度格式 ("double format") 位布局,返回指定浮点值的表示形式。
* 先通过调用doubleToLongBits获取到IEEE 754标准对应的整型数,然后再分别用
* DoubleConsts.EXP_BIT_MASK和DoubleConsts.SIGNIF_BIT_MASK两个掩码去判断是否为NaN,0x7ff8000000000000L对
* 应的即为NaN。
*/
public static long doubleToLongBits(double value) {
long result = doubleToRawLongBits(value);
// Check for NaN based on values of bit fields, maximum
// exponent and nonzero significand.
if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
DoubleConsts.EXP_BIT_MASK) &&
(result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
result = 0x7ff8000000000000L;
return result;
}
与doubleToLongBits
先对的方法是longBitsToDouble
,它返回对应于给定位表示形式的 double 值。如果参数是 0x7ff0000000000000L,则结果为正无穷大。如果参数是 0xfff0000000000000L,则结果为负无穷大。如果参数值在 0x7ff0000000000001L 到 0x7fffffffffffffffL 之间或者在 0xfff0000000000001L 到 0xffffffffffffffffL 之间,则结果为 NaN。
equals
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
首先判断是否为Double对象,如果是则比较doubleToLongBits
方法的返回值是否相等。
compareTo
public int compareTo(Double anotherDouble) {
return Double.compare(value, anotherDouble.value);
}
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
// doubleToRawLongBits,因为可能为NaN.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
d1小于d2则返回-1,反之则返回1。无法通过上述直接比较时则使用doubleToLongBits方法分别将d1和d2转成IEEE 754标准对应的整型数,然后再比较。相等则返回0,否则返回-1或1。注意:正0比负0大;NaN比任何非NaN的数都大。
版权属于:带翅膀的猫
本文链接:https://www.chengpengper.cn/archives/37/
转载时须注明出处及本声明