JDK之Float源码解析

概述

Java的Float类主要的作用就是对基本类型float进行封装,提供了一些处理float类型的方法,比如float到String类型的转换方法或String类型到float类型的转换方法,当然也包含与其他类型之间的转换方法

java float类型用IEEE754标准规定;

float占用4个字节,包括:

  • 1bit(符号位):0表示正数,1表示负数;
  • 8bits(指数位):float的偏移量为2^8 - 1,double的偏移量为2^11 - 1;
  • 23bits(尾数位):实际尾数部分中的小数点后的数值,规约浮点数使用标准的二进制科学计数法表示,其尾数范围在 [1,2),非规约浮点数的尾数部分范围在(0,1)


    这里写图片描述

示例:

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,和程序打印出来的一致。

类继承关系:

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

说明:这是java的规定,没必要深究为什么1.0/0.0不报错,不过1/0肯定报错

关于IEEE 754

在看Float前需要先了解IEEE 754标准,该标准定义了浮点数的格式还有一些特殊值,它规定了计算机中二进制与十进制浮点数转换的格式及方法。规定了四种表示浮点数值的方法,单精确度(32位)、双精确度(64位)、延伸单精确度(43位以上)与延伸双精确度(79位以上)。多数编程语言支持单精确度和双精确度,这里讨论的Float就是Java的单精确度的实现

类方法: {#类方法}

1.toString(float f):

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

FloatingDecimal:的作用是将float格式化转换,即什么时候用数字显示(位数小于8位),什么时候用指数显示(位数>=8位)
更加详细的在API中有说明

2.toHexString(float f):转成16进制的字符串(用科学计数法表示)

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.两个valueOf():将字符串/浮点数转换成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):和valueOf重复了

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

5.isNaN(float v):判断是不是一个‘不是数’(NaN和任何东西都不想等,包括他自己)

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

6.isInfinite(float v):判断是不是正无穷或者负无穷(这两个数使计算没有任何意义)

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

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

  • 根据 IEEE 754 的浮点“单一形式”中的位布局,返回指定浮点值的表示形式
  • 根据 IEEE 754 的浮点“单一形式”中的位布局,返回指定浮点值的表示形式,并保留非数字 (NaN) 值。
  • 返回对应于给定的位表示形式的 float 值。该参数被认为是符合 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):比较两个float的大小

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二进制表示

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

精度损失

看下面的程序:

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

打印出来的结果:

2.2
2.200000047683716

为什么会出现这种情况?

对于不能用二进制表示的 十进制小数,二进制小数位会进行循环,所以会损失精度。比如下面的语句会输出 true:

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

测试

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

output==>Infinity
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容