美文网首页
Java源码浅析,Float

Java源码浅析,Float

作者: Tomy_Jx_Li | 来源:发表于2018-09-26 16:24 被阅读40次

源码分析,基本上都加载注解上了,如有谬误,请指正,谢谢。
jdk1.8.0_161

/**
 * auther: jiyx
 * date: 2018/9/20.
 * float在计算机中占32字节,存储内容如下:
 *  1.符号位(1bit),0表示正数。1表示负数
 *  2.指数位(8bit),无符号数,范围0~255,但是指数位可能为负,所以这里有一个基数127.存储的时候需要真实指数+127
 *  3.尾数位(23位),有效数字。
 *  如8.25,二进制是1000.01,
 *  小数位求二进制方法(乘2取整法,即每一步将十进制小数部分乘以2,所得积的小数点左边的数字(0或1)作为二进制表示法中的数字,直到满足你的精确度为止)
 *  那么转换成指数形式就是1.00001 * 2^3
 *  那么指数位就是3 + 127,二进制表示法10000010
 *  符号位就是0,
 *  尾数位就是00001,这里可以直接省略小数点前的1,因为这里一直都是1,所以不需要
 *  那么最后8.25就是0100 0001 0000 0100 0000 0000 0000 0000
 */
public class Float extends Number implements Serializable {
    /**
     * 正无穷,相当于Float.intBitsToFloat(0x7f800000)
     */
    public static final float POSITIVE_INFINITY = 1.0f / 0.0f;

    /**
     * 负无穷,相当于Float.intBitsToFloat(0xff800000)
     */
    public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;

    /**
     * 非数字,相当于Float.intBitsToFloat(0x7fc00000)
     */
    public static final float NaN = 0.0f / 0.0f;

    /**
     * float的最大有限制,值为 (2减去2的负23次方)乘以2的127次方
     * 相当于Float.intBitsToFloat(0x7f7fffff)和十六进制的浮点字面值0x1.fffffeP+127f
     */
    public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f

    /**
     * float的最小的正正常值,2的负126次方,相当于16进制字面量0x1.0p-126f和Float.intBitsToFloat(0x00800000)
     */
    public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f

    /**
     * 最小的正数非零值,相当于16进制浮点字面量0x0.000002P-126f和Float.intBitsToFloat(0x1)
     */
    public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f

    /**
     * 有限浮点变量可能具有的最大指数,相当于Math.getExponent(Float.MAX_VALUE)
     */
    public static final int MAX_EXPONENT = 127;

    /**
     * 标准化浮点变量的最小指数可能有,相当于Math.getExponent(Float.MIN_NORMAL)
     */
    public static final int MIN_EXPONENT = -126;

    /**
     * float所占的bit数
     */
    public static final int SIZE = 32;

    /**
     * float所占的byte数
     */
    public static final int BYTES = SIZE / Byte.SIZE;

    /**
     * float的Class对象
     */
    @SuppressWarnings("unchecked")
    public static final Class<Float> TYPE = (Class<Float>) Class.getPrimitiveClass("float");

    /**
     * 返回float的字符串形式,
     * 1.如果是非字符串则返回NaN。
     * 2.还可能出现infinity(正无穷)和-infinity(负无穷)
     * 3.当输入的是0的时候,如果是正数返回0.0,负数返回-0.0
     * 4.当输入的数大于10的负3次方,小于10的7次方,返回的是十进制的整数位和小数位,小数位最后的多个零会合并成一个
     * 5.当输入的数小于10的负3次方,大于10的7次方,返回的是科学计数法表示的数, 如Integer.MAX_VALUE返回2.14748365E9
     */
    public static String toString(float f) {
        return FloatingDecimal.toJavaFormatString(f);
    }

    /**
     * 返回当前float的16进制形式
     * 1.输入的非数字,返回非数字
     * 2.还可能出现infinity(正无穷)和-infinity(负无穷)
     * 3.零返回0x0.0p0和-0x0.0p0
     * 4.标准的float将会返回类似0x1.097092p25,这种也是类似的科学计数法,
     *  小数点之前的不变,p后边的数代表的指数位,这里的25即2的25次方。
     * 5.如果数据低于正常float,即(FloatConsts.MIN_NORMAL),那么会返回0x0.开头的计数法
     *  如0x0.000002p-126
     *<table border>
     * <caption>Examples</caption>
     * <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
     * <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
     * <tr><td>{@code -1.0}</td>        <td>{@code -0x1.0p0}</td>
     * <tr><td>{@code 2.0}</td> <td>{@code 0x1.0p1}</td>
     * <tr><td>{@code 3.0}</td> <td>{@code 0x1.8p1}</td>
     * <tr><td>{@code 0.5}</td> <td>{@code 0x1.0p-1}</td>
     * <tr><td>{@code 0.25}</td>        <td>{@code 0x1.0p-2}</td>
     * <tr><td>{@code Float.MAX_VALUE}</td>
     *     <td>{@code 0x1.fffffep127}</td>
     * <tr><td>{@code Minimum Normal Value}</td>
     *     <td>{@code 0x1.0p-126}</td>
     * <tr><td>{@code Maximum Subnormal Value}</td>
     *     <td>{@code 0x0.fffffep-126}</td>
     * <tr><td>{@code Float.MIN_VALUE}</td>
     *     <td>{@code 0x0.000002p-126}</td>
     * </table>
     */
    public static String toHexString(float f) {
        // 低于正常float
        if (Math.abs(f) < FloatConsts.MIN_NORMAL
                && f != 0.0f) {
            // 首先调整当前的指数到double的指数精度,然后将返回的结果再替换回float的指数精度
            String s = Double.toHexString(Math.scalb((double) f,
                    /* -1022+126 */
                    DoubleConsts.MIN_EXPONENT -
                            FloatConsts.MIN_EXPONENT));
            return s.replaceFirst("p-1022$", "p-126");
        } else {
            // 因为Double返回的和Float一样,而且float在double范围内,所以直接使用Double
            return Double.toHexString(f);
        }
    }

    /**
     * 根据字符串返回Float对像
     * 1.入参不能是null,如果是抛出NullPointerException
     * 2.入参中前后的空格会使用trim消掉
     */
    public static Float valueOf(String s) throws NumberFormatException {
        return new Float(parseFloat(s));
    }

    /**
     * Float的自动装箱
     */
    public static Float valueOf(float f) {
        return new Float(f);
    }

    /**
     * 将指定的字符串解析为float
     */
    public static float parseFloat(String s) throws NumberFormatException {
        return FloatingDecimal.parseFloat(s);
    }

    /**
     * 判断指定数是否是非数字
     */
    public static boolean isNaN(float v) {
        return (v != v);
    }

    /**
     * 判断指定数是否是无穷数,不区分正负无穷
     */
    public static boolean isInfinite(float v) {
        return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
    }


    /**
     * 判断指定float是否在Float有效范围之内
     */
    public static boolean isFinite(float f) {
        return Math.abs(f) <= FloatConsts.MAX_VALUE;
    }

    /**
     * Float对象存储的float值
     */
    private final float value;

    /**
     * 构造函数
     */
    public Float(float value) {
        this.value = value;
    }

    /**
     * 构造函数
     */
    public Float(double value) {
        this.value = (float)value;
    }

    /**
     * 构造函数
     */
    public Float(String s) throws NumberFormatException {
        value = parseFloat(s);
    }

    /**
     * 判断当前存储的float是否是非数字
     */
    public boolean isNaN() {
        return isNaN(value);
    }

    /**
     * 判断当前存储的float是否是无穷数
     */
    public boolean isInfinite() {
        return isInfinite(value);
    }

    /**
     * toString
     */
    public String toString() {
        return Float.toString(value);
    }

    /**
     * 缩窄到byte
     */
    public byte byteValue() {
        return (byte)value;
    }

    /**
     * 缩窄到short
     */
    public short shortValue() {
        return (short)value;
    }

    /**
     * 缩窄到int
     */
    public int intValue() {
        return (int)value;
    }

    /**
     * 缩窄到long
     */
    public long longValue() {
        return (long)value;
    }

    /**
     * 返回本身的float
     */
    public float floatValue() {
        return value;
    }

    /**
     * 向上转型double
     */
    public double doubleValue() {
        return (double)value;
    }

    /**
     * hashcode
     */
    @Override
    public int hashCode() {
        return Float.hashCode(value);
    }

    /**
     * hashcode
     */
    public static int hashCode(float value) {
        return floatToIntBits(value);
    }

    /**
     * equals
     */
    public boolean equals(Object obj) {
        return (obj instanceof Float)
                && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
    }

    /**
     * 返回float的bit形式的十进制形式,这里的二进制形式与int等数据不同。
     * 参考开头对float二进制存储结构的介绍,也可以参考文末参考文章2、3
     * 
     * 正无穷0x7f800000,负无穷0xff800000,NaN返回0x7fc00000
     *
     * 这个方法其实就2步,首先将float转换为bit表示形式,然后以int的方式读取bit的表示,而不是以float形式读取
     */
    public static int floatToIntBits(float value) {
        int result = floatToRawIntBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & FloatConsts.EXP_BIT_MASK) ==
                FloatConsts.EXP_BIT_MASK) &&
                (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
            result = 0x7fc00000;
        return result;
    }

    /**
     * 同方法floatToIntBits一样,唯一的区别是,传入的数是NaN时,
     * 如果是floatToIntBits,返回的数是一样的,但是floatToRawIntBits,返回的是不同的
     * 可以通过Float.NaN 和 Math.sqrt(-1)来进行测试
     */
    public static native int floatToRawIntBits(float value);

    /**
     * 将float的bit形式所表示的十进制,转换成float的值。
     * 输入0x7f800000,输出Infinity
     * 输入0xff800000,输出-Infinity
     * 输入内容在输入0x7f800001和0x7fffffff之间 返回NaN
     * 输入内容在输入0xff800001和0xffffffff之间 返回NaN
     */
    public static native float intBitsToFloat(int bits);

    /**
     * 比较大小
     */
    public int compareTo(Float anotherFloat) {
        return Float.compare(value, anotherFloat.value);
    }

    /**
     * 静态比较
     * 0.0和-0.0是不相等的
     * NaN和-NaN是相等的
     * NaN和NaN是相等的
     * 但是要注意,Float.NaN == Float.NaN返回的是flase。
     * 可以参考isNaN方法。具体原理可以参考文末的参考6
     * 一般数与NaN不相等
     */
    public static int compare(float f1, float f2) {
        // 如果两个数都不为NaN时,直接进行比较
        if (f1 < f2)
            return -1;
        if (f1 > f2)
            return 1;

        // 不能是用floatToRawIntBits方法,因为可能出现NaNs
        int thisBits    = Float.floatToIntBits(f1);
        int anotherBits = Float.floatToIntBits(f2);

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

    /**
     * 求和
     */
    public static float sum(float a, float b) {
        return a + b;
    }

    /**
     * 取大值
     */
    public static float max(float a, float b) {
        return Math.max(a, b);
    }

    /**
     * 取小值
     */
    public static float min(float a, float b) {
        return Math.min(a, b);
    }

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -2671257302660747028L;
}

参考:
1.浮点数转二进制小数位转换规则
2.浮点数的二进制表示
3.float浮点数的二进制存储方式及转换
4.Java的NaN
5.wiki介绍NaN
6.Float.NaN的compare和==返回不一致问题

相关文章

网友评论

      本文标题:Java源码浅析,Float

      本文链接:https://www.haomeiwen.com/subject/uhcjoftx.html