[Java source code] Double

This time to look at Doublethe source code, based jdk1.8.0_181.jdk version, if wrong, please contact noted.

Foreword

DoubleIt is the doublebasic data type of packaging, and doubleis IEEE 754a standard double-precision 64bit floating point, specific IEEE 754some of the information here is no longer the standard describes in detail, it is recommended to see my previous article [Java source code] Float this I have a general understanding of the logic of the substantially uniform. For decimal floating point in Java, doubleit is the default type.

Double-precision (64 bit)

FIG continue using similar described,

  • sign: the sign bit, 1bit. 0 for positive, 1 for negative.
  • exponent: Exponent bits, 11bits. Double precision exponent part is -1022 + 1023 1024 plus an offset, the size of the index value (the special value 0 and 2047) from 1 to 2046
  • fraction: mantissa bits, 52bits.

Class information

public final class Double extends Number implements Comparable<Double>
复制代码

Definition with the finalidentification, representation is 不可继承的, further inherits Numberclass that implements Comparablethe interface

Attributes

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;
复制代码
  • POSITIVE_INFINITYRepresents positive infinity, value 0x7ff0000000000000L; standard definition exponent field are all 1, all 0 mantissa field
  • NEGATIVE_INFINITYRepresents negative infinity, value 0xfff0000000000000L; standard definition exponent field are all 1, all 0 mantissa field
  • NaNAbbreviation Not-a-Number, the standard is defined as the exponent field all 1, not all domains ending in 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
复制代码
  • MAX_VALUEThe maximum number of the statute is 0x1.fffffffffffffP+1023, here is a hexadecimal floating point representation, that is 0x7fefffffffffffffL, also (2 - Math.pow(2, -52) * Math.pow(2, 1023)), the calculated value1.7976931348623157e+308
  • MIN_NORMALThe minimum number of the statute is 0x1.0p-1022, here is a hexadecimal floating point representation, that is 0x0010000000000000L, also Math.pow(2, -1022), the calculated value2.2250738585072014E-308
  • MIN_VALUEThe minimum number of non-statute 0x0.0000000000001P-1022, there is a hexadecimal floating point number, i.e. 0x1L, also Math.pow(2, -1074), the calculated value4.9e-324
public static final int MAX_EXPONENT = 1023;

public static final int MIN_EXPONENT = -1022;
复制代码
  • MAX_EXPONENT It represents the maximum value of the index for 1023
  • MIN_EXPONENT It represents the minimum value of the index for-1022
public static final int SIZE = 64;
复制代码

It defines the bitnumber of bits

public static final int BYTES = SIZE / Byte.SIZE;
复制代码

Defines the Doubleobject number of bytes is fixed at 8 calcd

@SuppressWarnings("unchecked")
public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");
复制代码

Acquires class information, Double.TYPE == double.classthe two are equivalent

private final double value;
复制代码

DoubleIs a doublewrapper class, where the corresponding stored doubledata values

private static final long serialVersionUID = -9172774392245257468L;
复制代码

method

Construction method

public Double(double value) {
  this.value = value;
}

public Double(String s) throws NumberFormatException {
  value = parseDouble(s);
}
复制代码

Can pass doubleor Stringa type parameter, Stringthe internal argument constructor call to parseDoublea method for processing.

parseDouble method

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

Internal calls FloatingDecimal.parseDoubleachieve specific logic, wherein the specific processes and Floatthe like, can be viewed parsefloat methods appreciated described will not be repeated here. Return result corresponding to doublethe type of data values.

toString method

public static String toString(double d) {
  return FloatingDecimal.toJavaFormatString(d);
}
复制代码

Still we call FloatingDecimal.toJavaFormatStringa method, and the process Floatis basically the same, the result returns a corresponding string format.

toHexString method

public static String toHexString(double d) {
	// 判断是否是有限数值
  if (!isFinite(d) )
    // 对于 infinity 和 NaN, 直接调用 toString 返回
    return Double.toString(d);
  else {
    // 使用最大输出长度初始化StringBuilder容量
    StringBuilder answer = new StringBuilder(24);
		
    // 负数,增加符号标识
    if (Math.copySign(1.0, d) == -1.0)
      answer.append("-");            

    answer.append("0x");

    d = Math.abs(d);
		// 如果是0.0,直接输出返回
    if(d == 0.0) {
      answer.append("0.0p0");
    } else {
      // 判断是否为非规约数
      boolean subnormal = (d < DoubleConsts.MIN_NORMAL);

      // DoubleConsts.SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL
      // & 操作保留尾数位数据
      // | 操作是将最高位设为1,为了保留指数位的0,保留原来的长度,因为是个long类型整数
      long signifBits = (Double.doubleToLongBits(d)
                         & DoubleConsts.SIGNIF_BIT_MASK) |
        0x1000000000000000L;
	
      // 规约数为1.开头,非规约数为0.开头
      answer.append(subnormal ? "0." : "1.");

      // 使用Long.toHexString获取十六进制字符串,提取尾数位对应的字符串信息
      // 判断如果全为0,使用一个0替换
      // 如若不是,去除字符串尾部的所有0
      String signif = Long.toHexString(signifBits).substring(3,16);
      answer.append(signif.equals("0000000000000") ? // 13 zeros
                    "0":
                    signif.replaceFirst("0{1,12}$", ""));

      answer.append('p');
			
      // DoubleConsts.MIN_EXPONENT = -1022
      // 如果是非规约数,使用最小的指数位替换
      // 规约数,获取对应的指数值替代
      answer.append(subnormal ?
                    DoubleConsts.MIN_EXPONENT:
                    Math.getExponent(d));
    }
    return answer.toString();
  }
}
复制代码

Overall logic in the code comments have been described, clear and simple, results are returned corresponding hexadecimal string.

valueOf Method

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

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

There are two valueOfmethods, when the parameter is doubletime type, direct new Double(d)and return; string argument for calling parseDoubleis converted into doublea data value, then a new new object is returned.

isNaN method

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

public boolean isNaN() {
  return isNaN(value);
}
复制代码

Determining whether the NaNuse (v != v)is determined; specific NaNrules can be described with reference isNaN Method

isInfinite way

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

public boolean isInfinite() {
  return isInfinite(value);
}
复制代码

Judgment is not infinity, contains positive and negative infinity

isFinite method

public static boolean isFinite(double d) {
  return Math.abs(d) <= DoubleConsts.MAX_VALUE;
}
复制代码

Whether the absolute value of the input parameter by less than doublea maximum value of the type, the number of judgment is not limited

xxxValue method

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;
}
复制代码

Corresponding to the type of the return value, directly cast

hashCode method

@Override
public int hashCode() {
  return Double.hashCode(value);
}

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

>>>Unsigned right shift, high filled to 0. (bits ^ (bits >>> 32))32 is a logic high and low 32-bit XOR returns intinteger value hashCode

longBitsToDouble method

public static native double longBitsToDouble(long bits);
复制代码

longBitsToDoubleIt is a nativemethod, implemented by code c. Returns the corresponding doubledata value

  • Parameters 0x7ff0000000000000L, the result is positive infinity

  • Parameters 0xfff0000000000000L, the result is negative infinity

  • Parameters 0x7ff0000000000001L ~ 0x7fffffffffffffffLor 0xfff0000000000001L ~ 0xffffffffffffffffLthe time between, the result is NaN.

doubleToRawLongBits 方法

public static native long doubleToRawLongBits(double value);
复制代码

doubleToRawLongBitsIt is a nativemethod, implemented by the corresponding code c.

Results retention NaNvalues, the result is positive infinity 0x7ff0000000000000L; the result is negative infinity 0xfff0000000000000L; when the parameter is NaN, the actual result will be an input parameter corresponding to an integer value, as does the method doubleToLongBitsof NaNuniformly processing the return value

doubleToLongBits 方法

public static long doubleToLongBits(double value) {
  long result = doubleToRawLongBits(value);
  if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
        DoubleConsts.EXP_BIT_MASK) &&
      (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
    result = 0x7ff8000000000000L;
  return result;
}
复制代码

Substantially the doubleToRawLongBitssame method, except for increasing the NaNdetermination. If NaNthe direct return 0x7ff8000000000000L( for all NaNvalues of a unified return value processing ). Here recognition NaNlogic meet exponent field are all 1, all 0 mantissa field standards, as described in reference may floatToIntBits methods described.

equals method

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

First, judgment is not Doublethe object instance, and by doubleToLongBitsobtaining the corresponding two long integers, determines whether they match; It is noted that some special value determination logic.

System.out.println(new Double(0.0d).equals(new Double(-0.0d))); // false
System.out.println(new Double(Double.NaN).equals(new Double(-Double.NaN))); // true
复制代码

compare method

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

  // 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)
}
复制代码

And Floatconsistent, can refer to compare methods in the paragraphs that need attention is still -0.0, 0.0, Double.NaNand -Double.NaNa special kind of value, you can write your own conduct several test.

sum, min, max method

public static double sum(double a, double b) {
  return a + b;
}

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);
}
复制代码

The logic is simple, it's still important to note that -0.0, 0.0, Double.NaNand -Double.NaNa special kind of value, you can test yourself at the results, might surprise you, oh.

Special Note

Because doubleis 64bit, need to pay attention to the next doubleatom logic, here is the official document specifying Non-Atomic Treatment of doubleandlong , references explain:

For the purposes of the Java programming language memory model, a single write to a non-volatile longordoublevalue is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatilelongand doublevalues are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

Some implementations may find it convenient to divide a single write action on a 64-bit longor doublevalue into two write actions on adjacent 32-bit values. For efficiency's sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to perform writes to longand doublevalues atomically or in two parts.

Implementations of the Java Virtual Machine are encouraged to avoid splitting 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatileor synchronize their programs correctly to avoid possible complications.

For reasons of the Java programming language memory model, for no volatilemodification longor doublea single write operation, a write operation can be divided into two, each of the 32 operations. Which can result in false results thread to read 32-bit data from different combinations of thread writes.

For volatilemodified longand double, the write and read operations are atomic.

For write references, or whether it is 32-bit data value of 64, it is atomic.

Some implementations may find a single write data into two 64-bit writes the 32-bit data of neighboring easy. For the sake of efficiency, which is more particular implementation; the JVM implementations selection of free longand valuewriting atomic logic or two steps.

Encourage JVM implementation to avoid splitting logic 64 in possible. For programmers, encourage value added to the 64-bit shared volatileor synchronizestatement modified to avoid complex problems.

Can be seen from the above description, the atomicity problem may exist. But for now when most of the 64 machines and 64-bit JVM, the problem is generally ignored. But when you use the environment does not meet the requirements, please pay attention to the existence of this problem .

to sum up

The total code logic, Doubleand Floatlogic are basically the same, as are IEEE 754the number of different bit floating-point standard, mainly used to bring some gaps. If you already know float, then I understand that this is actually very simple.

At last

Blog Original Address: blog.renyijiu.com/post/java source ...

Guess you like

Origin juejin.im/post/5d69e9225188253eff7d70c7