JDK源码(9)-Double、Float

简介: JDK源码(9)-Double、Float

一、概述

 

这个千篇一律,Double是对基本数据类型double的包装,里面包含了double类型的字段。这个类也提供了一些将String和double转换为Double的方法,还有一些处理double的方法。

作者是:

* @author  Lee Boynton
 * @author  Arthur van Hoff
 * @author  Joseph D. Darcy
 * @since JDK1.0

image.gif

二、属性

提供了很多属性值,如下:

image.gif编辑

正无穷:POSITIVE_INFINITY:Double.longBitsToDouble(0x7ff0000000000000L)

负无穷:NEGATIVE_INFINITY:Double.longBitsToDouble(0xfff0000000000000L)

非数字:Not-a-Number (NaN):Double.longBitsToDouble(0x7ff8000000000000L)

最大值:MAX_VALUE:Double.longBitsToDouble(0x7fefffffffffffffL)

单精度最小值:MIN_NORMAL:Double.longBitsToDouble(0x0010000000000000L)

双精度最小值:MIN_VALUE:Double.longBitsToDouble(0x1L)

最大指数:MAX_EXPONENT:1023

最小指数:MIN_EXPONENT:-1022

三、主要方法

toString:很简单

toHexString:将double转换为16进制字符串,就是StringBuilder的字符串拼接:

public static String toHexString(double d) {
        if (!isFinite(d) )
            //如果是NaN或是无穷,直接返回对应的字符串形式
            return Double.toString(d);
        else {
            //初始化最大长度:24
            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 < DoubleConsts.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 ?
                              DoubleConsts.MIN_EXPONENT:
                              Math.getExponent(d));
            }
            return answer.toString();
        }
    }

image.gif

判断是否为NaN

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

image.gif

判断是否无限

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

image.gif

判断是否有限

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

image.gif

haseCode被重写了

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

image.gif

doubleToLongBits:很多方法中用到了这个方法,理解为将double转换为64位的long即可

    • 根据IEEE 754浮点“双格式”位布局返回指定浮点值的表示。
    • 位63(由掩码0x8000000000000000L选择的位)表示浮点数的符号。 位62-52(由掩码0x7ff0000000000000L选择的位)表示指数。 位51-0(由掩码0x000fffffffffffffL选择的位)表示浮点数的有效数(有时称为尾数)。
    • 如果参数为无穷大,则结果为0x7ff0000000000000L
    • 如果参数为负无穷大,则结果为0xfff0000000000000L
    • 如果参数是NaN,结果是0x7ff8000000000000L
    • 在所有情况下,结果是long整数,当给予longBitsToDouble(long)方法时,将产生与doubleToLongBits的参数相同的浮点值(除了所有NaN值都被折叠为单个“规范”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;
        }

    image.gif

    doubleToRawLongBits:与doubleToLongBits方法不同, doubleToRawLongBits不会将编码NaN的所有位模式折叠到单个“规范”NaN值。是一个native的方法了。

    public static native long doubleToRawLongBits(double value);

    image.gif

    compare:重写比较,注意Double.NaN返回是0

    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)
        }

    image.gif

    还有三个运算方法

    sum,max,min

    image.gif

    三、Float

    Float与Double非常类似,不再单独讲解

    相关文章
    |
    6月前
    |
    安全 前端开发 Java
    JDK源码级别彻底剖析JVM类加载机制
    JDK源码级别彻底剖析JVM类加载机制
    |
    6月前
    |
    缓存 Dubbo Java
    趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了
    趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了
    |
    6月前
    |
    存储 Java
    百度搜索:蓝易云【Java语言之float、double内存存储方式】
    由于使用IEEE 754标准进行存储,float和double类型可以表示非常大或非常小的浮点数,并且具有一定的精度。然而,由于浮点数的特性,它们在进行精确计算时可能会存在舍入误差。在编写Java程序时,需要注意使
    97 0
    |
    1月前
    |
    存储 C语言
    使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小
    【10月更文挑战第13天】使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小。
    88 1
    |
    3月前
    |
    算法 安全 Java
    深入JDK源码:揭开ConcurrentHashMap底层结构的神秘面纱
    【8月更文挑战第24天】`ConcurrentHashMap`是Java并发编程中不可或缺的线程安全哈希表实现。它通过精巧的锁机制和无锁算法显著提升了并发性能。本文首先介绍了早期版本中使用的“段”结构,每个段是一个带有独立锁的小型哈希表,能够减少线程间竞争并支持动态扩容以应对高并发场景。随后探讨了JDK 8的重大改进:取消段的概念,采用更细粒度的锁控制,并引入`Node`等内部类以及CAS操作,有效解决了哈希冲突并实现了高性能的并发访问。这些设计使得`ConcurrentHashMap`成为构建高效多线程应用的强大工具。
    55 2
    |
    4月前
    |
    存储 编译器 C++
    C++从遗忘到入门问题之float、double 和 long double 之间的主要区别是什么
    C++从遗忘到入门问题之float、double 和 long double 之间的主要区别是什么
    |
    4月前
    |
    存储 SQL 数据库
    MySQL设计规约问题之为何推荐用DECIMAL代替FLOAT和DOUBLE来存储精确浮点数
    MySQL设计规约问题之为何推荐用DECIMAL代替FLOAT和DOUBLE来存储精确浮点数
    |
    6月前
    |
    存储 C语言
    计算 int, float, double 和 char 字节大小
    计算 int, float, double 和 char 字节大小。
    80 3
    |
    5月前
    |
    Java Spring
    深入解析Spring源码,揭示JDK动态代理的工作原理。
    深入解析Spring源码,揭示JDK动态代理的工作原理。
    61 0
    |
    6月前
    |
    C#
    C# 字节数组与INT16,float,double之间相互转换,字符数组与字符串相互转换,
    C# 字节数组与INT16,float,double之间相互转换,字符数组与字符串相互转换,
    188 2