欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java源码分析---Double类(JDK14)

程序员文章站 2022-06-30 20:06:04
更多源码分析,请点击DoubleDouble 类将基本类型 double 的值包装在对象中。 Double 类型的对象包含一个类型为 double 的属性。另外,提供了几种将 double 转换为 String 和 String 转换为 double 的方法,以及其他在处理 double 类型时有用的方法。Double 类被 final 关键字修饰,不能被继承。Double 类继承自 Number 类,实现了 Comparable 、 Constable 、 ConstantDesc 接口。....

更多源码分析,请点击


Double

Double 类将基本类型 double 的值包装在对象中。 Double 类型的对象包含一个类型为 double 的属性。

另外,提供了几种将 double 转换为 StringString 转换为 double 的方法,以及其他在处理 double 类型时有用的方法。

Double 类被 final 关键字修饰,不能被继承。Double 类继承自 Number 类,实现了 ComparableConstableConstantDesc 接口。

public final class Double extends Number implements Comparable<Double>, Constable, ConstantDesc {
    private final double value;
    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;
    public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308
    public static final double MIN_NORMAL = 0x1.0p-1022; // 2.2250738585072014E-308
    public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324
    public static final int MAX_EXPONENT = 1023;
    public static final int MIN_EXPONENT = -1022;
    public static final int SIZE = 64;
    public static final int BYTES = SIZE / Byte.SIZE;
    public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");
}

value 为常量,用于保存 Double 对象所对应的基本类型 double 的值。

POSITIVE_INFINITY 为常量,表示正无穷。

NEGATIVE_INFINITY 为常量,表示负无穷。

NAN 为常量,表示值为 double 类型的非数字值。

MAX_VALUE 为常量,表示 double 类型的值所能表示的最大正数。(2-2-52)·21023

MIN_NORMAL 为常量,表示 double 类型标准浮点数的最小正数。2-1022

MIN_VALUE 为常量,表示 double 类型的值所能表示的最小正数。2-1074

MAX_EXPONENT 为常量,表示有限双精度变量可能具有的最大指数。

MIN_EXPONENT 为常量,表示归一化双精度变量可能具有的最小指数。

SIZE 为静态常量,用于表示二进制形式的 double 类型所需要的位数。

BYTES 为静态常量,用于表示二进制形式的 double 值所占的字节数。即8个字节。

TYPE 为静态常量,基本类型 doubleClass 对象。

toString(double)

返回 double 参数的字符串表示形式。

  • 如果参数为NaN,则结果为字符串“ NaN”。
  • 否则,结果是一个字符串,代表参数的符号和大小(绝对值)。如果符号为负,则结果的第一个字符为’-’(’\ u002D’);如果符号为正,则结果中不显示符号字符。至于大小m:
  • 如果m为无穷大,则用字符“ Infinity”表示;因此,正无穷大产生结果“无穷大”,而负无穷大产生结果“-无穷大”。
  • 如果m为零,则用字符“ 0.0”表示;因此,负零产生结果“ -0.0”,而正零产生结果“ 0.0”。
public static String toString(double d) {
    return FloatingDecimal.toJavaFormatString(d);
}

toString()

将该对象的值以字符串形式返回。

public String toString() {
    return toString(value);
}

toHexString(double)

返回double参数的十六进制字符串表示形式。

public static String toHexString(double d) {
    /*
     * Modeled after the "a" conversion specifier in C99, section
     * 7.19.6.1; however, the output of this method is more
     * tightly specified.
     */
    if (!isFinite(d) )
        // For infinity and NaN, use the decimal output.
        return Double.toString(d);
    else {
        // Initialized to maximum size of output.
        StringBuilder answer = new StringBuilder(24);

        if (Math.copySign(1.0, d) == -1.0)    // value is negative,
            answer.append("-");                  // so append sign info

        answer.append("0x");

        d = Math.abs(d);

        if(d == 0.0) {
            answer.append("0.0p0");
        } else {
            boolean subnormal = (d < Double.MIN_NORMAL);

            // Isolate significand bits and OR in a high-order bit
            // so that the string representation has a known
            // length.
            long signifBits = (Double.doubleToLongBits(d)
                               & DoubleConsts.SIGNIF_BIT_MASK) |
                0x1000000000000000L;

            // Subnormal values have a 0 implicit bit; normal
            // values have a 1 implicit bit.
            answer.append(subnormal ? "0." : "1.");

            // Isolate the low-order 13 digits of the hex
            // representation.  If all the digits are zero,
            // replace with a single 0; otherwise, remove all
            // trailing zeros.
            String signif = Long.toHexString(signifBits).substring(3,16);
            answer.append(signif.equals("0000000000000") ? // 13 zeros
                          "0":
                          signif.replaceFirst("0{1,12}$", ""));

            answer.append('p');
            // If the value is subnormal, use the E_min exponent
            // value for double; otherwise, extract and report d's
            // exponent (the representation of a subnormal uses
            // E_min -1).
            answer.append(subnormal ?
                          Double.MIN_EXPONENT:
                          Math.getExponent(d));
        }
        return answer.toString();
    }
}
  • 如果是浮点数 d 无穷大或者NaN,则直接调用 toString(double) 函数。

  • 浮点数 d 的绝对值是否小于 MAX_VALUE,则先初始化字符串最大长度为 24。

  • 先判断浮点数 d 是否为负数,如果是负数,需要在字符串最前面加上负号。

  • 在字符串中加入 “ 0x” ,表示为16进制表示形式。

  • 取浮点数 d 的绝对值,如果 d 的值等于0.0,则在字符串中加入“0.0p0”。

  • 调用 doubleToLongBits(double) 方法将浮点数 d 转换成十六进制bit位表示形式,和 SIGNIF_BIT_MASK 进行 操作,结果即尾数。然后进行 操作,将符号位置为1。

    public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;

  • 如果浮点数 d 小于最大标准数,则将“0.”加入字符串,否则,加入“1.”。

  • 将刚计算的尾数 signifBits 通过 Long.toHexString(long) 方法转为字符串,只截取其中3-16位尾数部分。(请点击查看 Long 类的源码分析,查看关于 Long.toHexString(long) 方法的详解

  • 如果尾数有多个零,则只保留一个0,这里通过正则表达式匹配(此处含义为从最后面开始匹配,0的个数最少为1个,最多为12个),调用 String.replaceFirst() 方法将指定位置的元素替换。(点击查看 String 类的源码分析了解该方法详情关于正则表达式点此了解详情

  • 然后在字符串中加入指数信息,通过 Math.getExponent(double) 方法获取浮点数 d 的指数。

isFinite(double)

如果该浮点数的绝对值小于浮点数最大值 MAX_VALUE ,则返回true,否则,返回false(无穷大或者NaN)。

public static boolean isFinite(double d) {
    return Math.abs(d) <= Double.MAX_VALUE;
}

doubleToLongBits(double)

根据[IEEE 754浮点数标准]([https://baike.baidu.com/item/IEEE%20754/3869922?fr=aladdin](https://baike.baidu.com/item/IEEE 754/3869922?fr=aladdin)),返回指定浮点值的表示形式。(不了解该标准的可以点击链接了解详情)

位63表示浮点数的符号。位62-52表示指数。位51-0表示浮点数的有效位(有时称为尾数)。

如果参数为正无穷大,则结果为0x7ff0000000000000L。

如果参数为负无穷大,则结果为0xfff0000000000000L。

如果参数为NaN,则结果为0x7ff8000000000000L。

public static long doubleToLongBits(double value) {
    if (!isNaN(value)) {
        return doubleToRawLongBits(value);
    }
    return 0x7ff8000000000000L;
}

doubleToRawLongBits(double)

本地静态方法doubleToLongBits(double) 方法的具体实现,具体功能一致。该方法在本地采用C/C++实现。

public static native long doubleToRawLongBits(double value);

valueOf(double)

double 类型的值转为 Double 对象。

public static Double valueOf(double d) {
    return new Double(d);
}

valueOf(String)

将字符串 s 转为 Double 对象。

调用 parseDouble(String) 方法先将字符串 s 转为 double 类型,然后调用 Double 类的构造方法实现。

public static Double valueOf(String s) throws NumberFormatException {
    return new Double(parseDouble(s));
}

parseDouble(String)

将字符串 s 转换为 double 类型的值。 调用 FloatingDecimal.parseDouble(String) 方法实现。

public static double parseDouble(String s) throws NumberFormatException {
    return FloatingDecimal.parseDouble(s);
}

isNaN(double)

如果浮点数 v 是NaN,则返回true,否则,返回false。

public static boolean isNaN(double v) {
    return (v != v);
}

isNaN()

如果该对象的值是否是 NaN,则返回true,否则,返回false。

public boolean isNaN() {
    return isNaN(value);
}

isInfinite(double)

如果浮点数 v 是无穷,则返回true,否则,返回false。

public static boolean isInfinite(double v) {
    return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}

isInfinite()

如果该对象的值是无穷,则返回true,否则,返回false。

public boolean isInfinite() {
    return isInfinite(value);
}

byteValue()shortValue()intValue()longValuefloatValue()doubleValue() 等方法实现简单,不再赘述。

hashCode(double)

返回浮点数 value 的哈希值。将 value 数据按 bit 转为16进制,逻辑右移32为后再与自身求异或。转为 int 形式即为哈希值。(即将高32位于低32位求异或)

public static int hashCode(double value) {
    long bits = doubleToLongBits(value);
    return (int)(bits ^ (bits >>> 32));
}

equals(Object)

将此对象与指定对象进行比较。 当且仅当参数不为null且是一个 Double 对象,doubleToLongBitsdouble) 方法在应用于每个值时返回相同的 long 值时,才将两个 double 值视为相同。

如果d1和d2都表示 NaN ,则即使 NaN == NaN的值为false,equals方法也将返回true。

如果d1表示+0.0,而d2表示-0.0,反之亦然,即使+0.0 ==-0.0的值为true,相等测试的值为false。

public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

longBitsToDouble(long)

本地静态方法,返回对应于给定位表示形式的double值。根据IEEE 754浮点“双格式”位布局,该参数被认为是浮点值的表示。

如果参数为0x7ff0000000000000L,则结果为正无穷大。

如果参数为0xfff0000000000000L,则结果为负无穷大。

如果参数是0x7ff0000000000001L到0x7fffffffffffffffffL或0xfff0000000000001L到0xffffffffffffffffL范围内的任何值,则结果为NaN。

Java提供的IEEE 754浮点运算无法区分具有不同位模式的相同类型的两个NaN值。 NaN的不同值只能通过使用 doubleToRawLongBits 方法来区分。

public static native double longBitsToDouble(long bits);

compare(double, double)

比较给定的两个浮点值的大小。

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

    // Cannot use doubleToRawLongBits because of possibility of NaNs.
    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)
}

sum(double, double)max(double, double)min(double, double) 等方法实现简单,不再赘述。

describeConstable()

Constable 接口中的方法。点此了解详情。

@Override
public Optional<Double> describeConstable() {
    return Optional.of(this);
}

resolveConstantDesc(MethodHandles.Lookup)

ConstantDesc 接口中的方法,点此了解详情。

@Override
public Double resolveConstantDesc(MethodHandles.Lookup lookup) {
    return this;
}

更多源码分析,请点击

本文地址:https://blog.csdn.net/wrz_1028/article/details/107699067