Skip to main content

JVM源码解读-Float类

finen...About 8 minJava-SourceJava-Source

1.类图

Float-Class
Float-Class

2.存储位置

  • Float类中的静态属性存储在方法区中的静态区。
  • 通过new Float()方法创建出来的对象存储在堆区。

3.了解IEEE 754

3.1 IEEE 754简介

在看Float前需要先了解IEEE 754标准,该标准定义了浮点数的格式还有一些特殊值,它规定了计算机中二进制与十进制浮点数转换的格式及方法。规定了四种表示浮点数值的方法,单精确度(32位)、双精确度(64位)、延伸单精确度(43位以上)与延伸双精确度(79位以上)。
多数编程语言支持单精确度和双精确度,该标准的全称为IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985),又称IEC 60559:1989,微处理器系统的二进制浮点数算术(本来的编号是IEC 559:1989)。后来还有“与基数无关的浮点数”的“IEEE 854-1987标准”,有规定基数为2跟10的状况。最新标准是“ISO/IEC/IEEE FDIS 60559:2010”。
Float就是Java的单精度实现。

3.2 IEEE 754单精度浮点数表示

浮点数由三部分组成,分别是符号位s、指数e和尾数f。

在IEEE754标准中,一个规格化的32位浮点数x的真值表示为
x = (−1)s∗(1.f)∗2(e−127)
e = E - 127

其中尾数域所表示的值是1.f。由于规格化的浮点数的尾数域最左位(最高有效位)总是1,故这一位经常不予存储,而认为隐藏在小数点的左边。于是用23位字段可以存储24位有效数。

我们举个例子来看,二进制的“01000001001101100000000000000000”表示的浮点数是啥?

符号位为0,表示正数。
指数为“10000010”,减去127后为3。
尾数对应的值为“1.011011”。
于是最终得到浮点数为“1011.011”,转成十进制为“11.375”。

4.源码解读

4.1 属性说明

public final class Float extends Number implements Comparable<Float> {
    // System.out.println(Float.POSITIVE_INFINITY == Float.intBitsToFloat(0x7f800000)); // true
    // System.out.println(Float.POSITIVE_INFINITY);  ==> Infinity
    //  用来表示正无穷大,按照IEEE 754浮点标准规定,任何有限正数除以0为正无穷大,正无穷的值为0x7f800000。
    public static final float POSITIVE_INFINITY = 1.0f / 0.0f;

    // System.out.println(Float.NEGATIVE_INFINITY == Float.intBitsToFloat(0xff800000)); // true
    // System.out.println(Float.NEGATIVE_INFINITY); // -Infinity
    // 用来表示负无穷大,任何有限负数除以0为负无穷的,负无穷的值为0xff800000。
    public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;

    // System.out.println(Float.isNaN(Float.intBitsToFloat(0x7fc00000))); // true
    // System.out.println(Float.intBitsToFloat(0x7fc00000)); // NaN
    // NaN 用来表示处理计算中出现的错误情况,比如0除以0或负数平方根。对于单精度浮点数,IEEE 标准规定 NaN 的指数域全为 1,且尾数域不等于零的浮点数。它并没有要求具体的尾数域,所以 NaN 实际上不非是一个,而是一族。Java这里定义的值为0x7fc00000。
    public static final float NaN = 0.0f / 0.0f;
    
    // System.out.println(Float.MAX_VALUE == Float.intBitsToFloat(0x7f7fffff)); // true
    // System.out.println(Float.intBitsToFloat(0x7f7fffff)); // 3.4028235E38
    // 用来表示最大的浮点数值,它定义为0x1.fffffeP+127f,这里0x表示十六进制,1.fffffe表示十六进制的小数,P表示2,+表示几次方,这里就是2的127次方,最后的f是转成浮点型。所以最后最大值为3.4028235E38。
    public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f
    
    // System.out.println(Float.MIN_NORMAL == Float.intBitsToFloat(0x00800000)); // true
    // System.out.println(Float.intBitsToFloat(0x00800000)); // 1.17549435E-38
    // 1.6开始存在
    // 用来表示最小标准值,它定义为0x1.0p-126f,这里其实就是2的-126次方的了,值为1.17549435E-38f。
    public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f

    // System.out.println(Float.MIN_VALUE == Float.intBitsToFloat(0x1)); // true
    // System.out.println(Float.intBitsToFloat(0x1)); // 1.4E-45
    // 用来表示浮点数最小值,它定义为0x0.000002P-126f,最后的值为1.4e-45f
    public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f
    
    // System.out.println(Math.getExponent(Float.MAX_VALUE) == Float.MAX_EXPONENT); // true
    // System.out.println(Math.getExponent(Float.MAX_VALUE)); // 127
    // 1.6开始
    // 用来表示指数的最大值,这里定为127,这个也是按照IEEE 754浮点标准的规定。
    public static final int MAX_EXPONENT = 127;
    
    // System.out.println(Math.getExponent(Float.MIN_NORMAL) == Float.MIN_EXPONENT); // true
    // System.out.println(Float.MIN_EXPONENT); // -126
    // 1.6开始
    // 用来表示指数的最小值,按照IEEE 754浮点标准的规定,它为-126。
    public static final int MIN_EXPONENT = -126;
    
    // 用来表示二进制float值的比特数,值为32,静态变量且不可变。
    public static final int SIZE = 32;
    
    // 用来表示二进制float值的字节数,值为SIZE除于Byte.SIZE,结果为4字节,表示存储一个Float类型的变量占用4字节。
    public static final int BYTES = SIZE / Byte.SIZE;
}

4.2 方法说明

Float构造方法

Float构造方法有3个,第一个是将float但精度浮点数转为Float值,第二个是将double值的双精度浮点数转为单精度浮点数,该转化可能出现精度丢失的情况。
第三个构造方法是将字符串转为单精度浮点数。

public final class Float extends Number implements Comparable<Float> {
    public Float(float value) {
        this.value = value;
    }
    public Float(double value) {
        this.value = (float)value;
    }
    public Float(String s) throws NumberFormatException {
        value = parseFloat(s);
    }
}

toHexString方法

  • 该方法是将浮点数转为16进制数的字符串
Floating-point ValueHexadecimal String
1.00x1.0p0
0.250x1.0p-2
Float.MAX_VALUE0x1.fffffep127
Float.MIN_VALUE0x0.000002p-126
public final class Float extends Number implements Comparable<Float> {
    public static String toHexString(float f) {
        if (Math.abs(f) < FloatConsts.MIN_NORMAL
                &&  f != 0.0f ) {// float subnormal
            // Adjust exponent to create subnormal double, then
            // replace subnormal double exponent with subnormal float
            // exponent
            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 string will be the same as float string
            return Double.toHexString(f);
    }
}
public class FloatDemoTest {
    @Test
    public void testToHexString() {
        System.out.println(Float.toHexString(1.0f)); //0x1.0p0
    }
}

valueOf方法

改方法有两个,一个是将字符串转为单精度浮点数,一个是将float值转化为Float对象

public final class Float extends Number implements Comparable<Float> {
    public static Float valueOf(String s) throws NumberFormatException {
        return new Float(parseFloat(s));
    }
    public static Float valueOf(float f) {
        return new Float(f);
    }
}
public class FloatDemoTest {
    @Test
    public void testValueOf() {
        System.out.println(Float.valueOf(1.01f)); // 1.01
        System.out.println(Float.valueOf("1.01")); // 1.01
        System.out.println(Float.valueOf("+1.01f")); // 1.01
        System.out.println(Float.valueOf("-1.01f")); // -1.01
        System.out.println(Float.valueOf("1.01F")); // 1.01
        System.out.println(Float.valueOf("1.01d")); // 1.01
        System.out.println(Float.valueOf("1.01I")); // java.lang.NumberFormatException: For input string: "1.01I"
    }
}

parseFloat方法

该是Java中的内置方法,该方法返回一个新的float,该新float初始化为指定的String表示的值,这由Float类的valueOf方法完成。

public final class Float extends Number implements Comparable<Float> {
    public static float parseFloat(String s) throws NumberFormatException {
        return FloatingDecimal.parseFloat(s);
    }
}

isNaN方法

  • 该方法是判断是否是非数字的值(NAN), NaN是Not a Number的缩写。
public final class Float extends Number implements Comparable<Float> {
    public boolean isNaN() {
        return isNaN(value);
    }
    public static boolean isNaN(float v) {
        return (v != v);
    }
}

isInfinite与isInfinite方法

  • isInfinite()方法用于检查此Float对象的无穷大(即正无穷大或负无穷大)

  • isFinite() 方法如果传递的参数是有限浮点数,则返回 true,否则返回 false(在 NaN 和无穷大参数的情况下)。

public final class Float extends Number implements Comparable<Float> {
    public static boolean isInfinite(float v) {
        return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
    }
    public static boolean isFinite(float f) {
        return Math.abs(f) <= FloatConsts.MAX_VALUE;
    }
}
public class FloatDemoTest {
    @Test
    public void testInfiniteAndFinite() {
        System.out.println(Float.isInfinite(Float.POSITIVE_INFINITY)); // true
        System.out.println(Float.isInfinite(0.05f));                // false
        System.out.println(Float.isFinite(0.05f));                  // true
        System.out.println(Float.isFinite(Float.POSITIVE_INFINITY));   // false
    }
}

floatToIntBits方法

Float类中的floatToIntBits()方法是Java中的内置函数,它根据IEEE 754浮点“single format”位布局返回指定浮点值的表示形式。

返回值:该函数返回表示浮点数的整数位。以下是特殊情况:

  • 如果参数为正无穷大,则结果为0x7f800000。
  • 如果参数为负无穷大,则结果为0xff800000。
  • 如果参数为NaN,则结果为0x7fc00000。
public final class Float extends Number implements Comparable<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;
    }
}

sum/max/min方法

  • sum方法是用来计算两个float值之和。
  • max方法是用来查找两个float值的最大值。
  • min方法是用来查找两个float值的最小值。
public final class Float extends Number implements Comparable<Float> {
    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);
    }
}

floatToRawIntBits/intBitsToFloat native方法()

  • Float类中的floatToRawIntBits()方法是Java中的内置函数,该函数根据IEEE 754浮点“single format”位布局返回指定浮点值的表示形式,并保留Not-a-Number(NaN)值。

返回值:该函数返回代表浮点数的位。但是,有3种特殊情况:

* 如果参数为正无穷大,则结果为0x7f800000。
* 如果参数为负无穷大,则结果为0xff800000。
* 如果参数为NaN,则结果为0x7fc00000。
  • Java Float 类的 intBitsToFloat() 方法返回与给定位表示相关的浮点值。根据 IEEE 754 浮点 'single format' 位布局,传递的参数被视为浮点值的表示。

此方法返回具有相同位模式的浮点值。

* 如果传递的参数为 0X7f800000,则返回的结果为正无穷大。
* 如果传递的参数为 0Xff800000,则返回的结果为负无穷大。
* 如果传递的参数在 0x7f800001 到 0x7fffffff 之间的范围内或在 0xff800001 到 0xffffffff 之间的范围内,则返回的结果为 Nan。
public final class Float extends Number implements Comparable<Float> {
    public static native int floatToRawIntBits(float value);

    public static native float intBitsToFloat(int bits);
}

5.说明

  • 需要精确计算时不要使用float和double,如果需要精度计算,请使用BigDecimal
  • 不能用浮点数作为循环变量,浮点数不能为循环因子,精度问题会导致 (float)2000000000 == 2000000050为true
  • 浮点型数据判断相等不能直接使用,应采用如下方式
float a =...;
float b =...;
if (Math.abs(a-b) < 1E-6f) {
      ...
} 
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8