Float source code analysis of JDK

Overview

The main function of Java's Float class is to encapsulate the basic type float, and provide some methods for dealing with float types, such as the conversion method from float to String type or the conversion method from String type to float type, and of course it also includes other types. conversion method of

The java float type is specified by the IEEE754 standard;

float occupies 4 bytes, including:

  • 1bit (sign bit): 0 means positive number, 1 means negative number;
  • 8bits (exponent bits): the offset of float is 2^8 - 1, and the offset of double is 2^11 - 1;
  • 23bits (mantissa bits): the value after the decimal point in the actual mantissa part. The reduced floating point number is represented by standard binary scientific notation, and its mantissa range is [1, 2), and the mantissa part of the non-reduced floating point number is in the range (0, 1)
    write picture description here

Example:

8.25 的 float 表示
整数8的二进制:1000
小数0.25的二进制:.01
8.25整体的二进制:1000.01 → 1.00001 * 2^3
小数点左移 3 位,所以指数部分(3 + 127) = 130,二进制是 10000010
尾数:去掉小数点前面的1,为 00001,补充到 23 位,000 0100 0000 0000 0000 0000
最终 8.25 在内存中存储的二进制是:0100 0001 0000 0100 0000 0000 0000 0000
9.5 的 float 表示
9.5的二进制:1001.1 -> 1.0011 * 2^3
指数位是 (3 + 127)=130,二进制 10000010
尾数是 0011 000000 0000000000 000
最终 9.5 在内存中存储的二进制是:010000010 0011 000000 0000000000 000,和程序打印出来的一致。

Class inheritance relationship:

public final class Float extends Number implements Comparable<Float> {
    public static final float POSITIVE_INFINITY = 1.0f / 0.0f; // 正无穷大
    public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; // 负无穷大

    public static final float NaN = 0.0f / 0.0f; // Not a Number(不是数)(输出就是NaN)

    // 指数部分的最大值(指数位的长度1个字节):127,最小值为-126
    public static final int MAX_EXPONENT = 127;
    public static final int MIN_EXPONENT = -126;

    // 一个float占4个字节(32位)
    public static final int SIZE = 32;
}

Explanation: This is the rule of java, there is no need to go into why 1.0/0.0 does not report an error, but 1/0 must report an error

About IEEE 754

Before looking at Float, you need to understand the IEEE 754 standard. This standard defines the format of floating-point numbers and some special values. It specifies the format and method of converting binary and decimal floating-point numbers in computers. Four methods of representing floating-point values ​​are specified, single precision (32 bits), double precision (64 bits), extended single precision (more than 43 bits) and extended double precision (more than 79 bits). Most programming languages ​​support single-precision and double-precision, and the Float discussed here is the implementation of Java's single-precision

Class method: {#class method}

1.toString(float f):

public String toString() {
    return Float.toString(value);
}
public static String toString(float f) {
    return FloatingDecimal.toJavaFormatString(f);
}

FloatingDecimal: The function is to format and convert the float, that is, when to display it as a number (less than 8 digits) and when to display it as an exponent (number of digits >= 8 digits).
More details are described in the API.

2.toHexString(float f): Convert to hexadecimal string (represented in scientific notation)

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

3. Two valueOf(): Convert strings/floats to objects of type Float

public static Float valueOf(String s) throws NumberFormatException {
    return new Float(parseFloat(s));
}
public static Float valueOf(float f) {
    return new Float(f);
}

4.parseFloat(String s): duplicated with valueOf

public static float parseFloat(String s) throws NumberFormatException {
    return FloatingDecimal.parseFloat(s);
}

5.isNaN(float v): Determine whether it is a 'not a number' (NaN and anything do not want to wait, including himself)

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

6.isInfinite(float v): Determine whether it is positive infinity or negative infinity (these two numbers make the calculation meaningless)

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

7.floatToRawIntBits(float value) floatToIntBits(float value) intBitsToFloat(int bits):

  • Returns the representation of the specified floating-point value according to the bit layout in the floating-point "single form" of IEEE 754
  • Returns a representation of the specified floating-point value according to the bit layout in the floating-point "single form" of IEEE 754, preserving not-a-number (NaN) values.
  • Returns the float value corresponding to the given bit representation. This parameter is considered to be a representation of a floating-point value according to the bit layout in the floating-point "single form" of IEEE 754
public static native float intBitsToFloat(int bits);
 public static native int floatToRawIntBits(float value);
 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;
    }

8.compare(float f1, float f2): Compare the size of two floats

public static int compare(float f1, float f2) {
    if (f1 < f2)
        return -1;           // Neither val is NaN, thisVal is smaller
    if (f1 > f2)
        return 1;            // Neither val is NaN, thisVal is larger

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

float binary representation

int i = Float.floatToIntBits(8.25f);
System.out.println(Integer.toBinaryString(i)); // output==>1000001000001000000000000000000

loss of precision

See the program below:

float f = 2.2f;  
double d = (double) f;  
System.out.println(f);  
System.out.println(d);

The result printed out:

2.2
2.200000047683716

Why does this happen?

For decimal fractions that cannot be represented in binary, the binary decimal places are cycled, so precision is lost. For example, the following statement will output true:

System.out.println(2.2f == 2.20000001f);

test

float num = 4.0f / 0.0f;
System.err.println(num); // java中规定分母不能为0,但是浮点数计算中不抛异常

output==>Infinity

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325673695&siteId=291194637