一、开篇:

首先,先让大家看下面这个例子:

public class Demo01 {

public static void main(String[] args) {

float f1=0.2F;

float f2=0.3F;

float f3=f2-f1;

System.out.println(f3);

}

}

这个连小孩子都能算出的问题,答案一定是0.1了,0.3-0.2嘛,是吧。但是,在计算机的内部运算情况却不是这样,我们不妨输出一下,答案却是0.10000001。如果我们去问老师,老师会告诉你,这是精度的问题,浮点数的精度会精确到很多位的,你们只要记住这个就好了。老师说的也对,这的确是精度的问题,但是有精度也不会导致错误吧?我们是主学计算机的,并不是什么机械、土木的,这个现象就一定要解决,一定要剖解。好的,下面会具体会给你讲解这个Float。

二、关于Int:

在讲Float时,首先咱们先来看看Int在内存中的存储情况。Int,四个字节,三十二个比特位,其中前31位为有效位,第32位为符号位,有效范围-21亿到+21亿,也就是-2^31……2^31-1。

第一个字节    第二个字节    第三个字节    第四个字节

0101 0000  0000 0000  0000 0000  0000 0000

蓝色:符号位 ( 31 )

绿色:有效位 (0--30 )

这就是0x50000000的int类型整数在内存中的形式,我们口算其实就可以算出它的结果,很简单的。两个1分别在30和28的位置上,也就是2^30+2^28,这出的结果是1342177280,和在控制台输出是一样的答案。所以说整数类型无论存储形式还是计算都很简单。

三、关于Float:

大家都知道Float类型,和Int类型一样,同样的四个字节,三十二个比特位,第32位为符号位,数字大小为

1.4E-45……3.4E+38,-1.4E-45……-3.4E+38。至于前面的31位就不清楚了吧。好的,我们还以0x50000000来举例,记住,这回这个数字可不是上边那个整数了,这个是浮点数了奥。

第一个字节    第二个字节    第三个字节    第四个字节

0101 0000   0000 0000  0000 0000  0000 0000

蓝色:符号位( 31 )

黄色:幂指数位(23--30)

绿色:有效位 (0--22)

通过上图我们看到,浮点数的32位在内存的排列情况,其中的前23位是有效位,占23个比特位,第24位到31位为幂指数位,占8个比特位,第32位依旧是符号位。

既然已经知道浮点数在内存中的存储情况,那么具体怎么计算的啊,看上边的那个数字,它的有效位是0,输出的该不会是0吧?我只是想说,额,不好说,下面看我慢慢说。

在java JDK中,float包下有个方法是intBitsToFloat,它的返回对应于给定位表示形式的 float 值。根据 IEEE 754 浮点“单一格式”位布局,该参数被视为浮点值表示形式。

它规定如果参数为 0x7f800000,则结果为正无穷大。

那么,我们就看看这个数字在内存中是怎么存储的。0x代表十六位存储格式,7f8,很明显,是八个一,后面都是0。

第一个字节    第二个字节    第三个字节    第四个字节

0111 1111   1000 0000  0000 0000  0000 0000

蓝色:符号位( 31 )

黄色:幂指数位(23--30)

绿色:有效位(0--22)

这个就是所谓的浮点数的正无穷大的数字。那么,我们一定好奇,比这个数字还要大的数字,那会是多少那,比这个数还大,也就是浮点数依旧都是“1”,只是有效位顺便填个“1”就是了,好的,现在我们就输出一下。 public class Demo02 {     public static void main(String[] args) {         System.out.println(Float.intBitsToFloat(0x7f800000));         System.out.println(Float.intBitsToFloat(0x7f800001));     } }       这两个输出的结果是:Infinity、NaN。     Infinity这个词大家都知道,就是无穷大的,而NaN,就是Not a Number,代表不是一个数字。Float规定,超出最大范围,就变成了一个不是数字的数字。 好的,关于float的无穷大和比无穷还要大的不是数字我们都知道了,下面大家可以试着猜想一下,float的最大数究竟是多少那,都说是3.4E+38,这个是具体在内存中怎么存储的那? 下面我们就具体分析下这个数的产生。最大值,顾名思义,就是比无穷大小那么的一点点,那这一点点,究竟是怎么样的一点点那?无穷大的有效位全是“0”,幂指数全是“1”,那么一点点就是,比幂指数小那么一点,而有效位要置为最大,也就是幂指数八位最后一位置为“0”,有效位全部置为“1”,在内存中的存储形势即:

第一个字节    第二个字节    第三个字节    第四个字节

0111 1111    01111 1111  1111 1111   1111 1111

蓝色:符号位( 31 )

黄色:幂指数位(23--30)

绿色:有效位 (0--22)

这就是Float的最大数,也就是3.4E+38,我们也可以在MyEclipse中打印出来,Float.intBitsToFloat(0x7f7fffff),输出的结果是3.4028235E38。
    下面我们就来探讨最小的float了。有人会想,那就是把最大数的符号位置为“1”,就搞定了。当然正确,那的确是最小数,但是我们这里提的是,关于正数的最小数。其实大家根据上边的三个,已经有了自己的答案,的确,就是有效位第一位是“1”,幂指数全部是“0”,也就是
         第一个字节    第二个字节    第三个字节    第四个字节

0000 0000  0000 0000  0000 0000 0000 0001

蓝色:符号位( 31 )

黄色:幂指数位(23--30)

绿色:有效位 (0--22)

好的,下面我们就来输出下,
    public class Demo03 {
        public static void main(String[] args) {
            System.out.println(Float.intBitsToFloat(0x7f7fffff));    //最大数
            System.out.println(Float.intBitsToFloat(0x00000001));  //最小数
        }
    }
        输出结果分别为:3.4028235E38、   1.4E-45。

根据这几个实例,下面我们就可以回顾开始的那个问题了,0x50000000,究竟是不是0的问题了,打印Float.intBitsToFloat(0x50000000),在控制台它的输出结果是8.5899346E9,看,不是0吧。
    其实,这篇文章在这应该可以结尾的,我们知道了Float数的具体存储情况,知道了最大数,最小数,无穷大,比无穷大还要大的不是数的数。但是,我们只是知道了内部存储情况,却还不知道它的内部运算情况,就像0x50000000,我们只是知道不是“0”,但是有效位是“0”,怎么最后输出结果就不是“0”了那?
    在JDK有写出,浮点数的内部运算情况,即:
设 s、e 和 m 为可以通过以下参数进行计算的三个值; 
int s = ((bits >> 31) == 0) ? 1 : -1;
int e = ((bits >> 23) & 0xff);
int m = (e == 0) ?
                (bits & 0x7fffff) << 1 :
                (bits & 0x7fffff) | 0x800000;
     那么浮点结果等于算术表达式 s·m·2e-150 的值。 
    在这里面,s是符号位,e是幂指数,m是有效位,(bits>>数字)意思是取出,也就是取出有效位或者幂指数位。下面我们就运用计算器来计算出最大数,最小数和0x50000000的数字。
  1)最大数,0x7f7fffff, 根据上边的规定,s==0,即符号位+1;幂指数8位被取出后变为0xfe,也就是第一位为“0”,后七位都是“1”,那么e这个数字就是254;有效位中,e不为“0”,所以使用 (bits & 0x7fffff) | 0x800000,取出有效位为23个“1”,在与0x800000相或,得到24个“1”,数字表示为2^24-1;现在是s,e,m都有了,根据公式 s·m·2e-150计算,+1*(2^24-1)*(2^(254-150)) 就得到最大数字3.4028235E38。
  2)最小数,0x00000001。根据规定,s==0,即符号位+1;幂指数8位都为“0”,即为“0”;有效位为“1”,因为e==0,所以用(bits & 0x7fffff) << 1 个计算m,取出“1”,向右移一位,变为“2”,也就是m=2;根据公式 s·m·2e-150计算,+1*(2^1)*(2^(0-150)) 就得到最小数字1.401298464E-45。
  3)0x50000000。根据规定,s==0,即符号位+1;取出幂指数位,10100000,128+32,也就是幂指数e为160;有效位中,e不为“0”,所以使用 (bits & 0x7fffff) | 0x800000,取出有效位为23个“0”,在与0x800000相或,也就是得0x800000,也就是说m就是对应的十六进制的0x800000,数字表示为2^23;现在是s,e,m都有了,根据公式 s·m·2e-150计算,+1*(2^23)*(2^(160-150)) 就得到数字8.5899346E9。
    通过以上的理解,我想大家一定对Float认识的很清楚了吧,也可以返回咱们开篇的那个小数的问题了。也就是在把十进制转换为二进制的时候容易造成精度丢失,故而两个数相减得到无尽的小数。
    浮点数还有比Float还有精确的,就是Double,下面就是参照Float来看看Double数字在内存内部的存储情况。

S:符号位  E:幂指数 M:有效位
             float类型:
                 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM        
                   S:1     E:8    M:23

double类型:
                  SEEE EEEE EEEE MMMM  MMMM MMMM MMMM MMMM MMMM
                 MMMM MMMM MMMM MMMM MMMM MMMM MMMM 
                    S:1   E:11   M:52

四、总结

由于浮点数的精度非常高,所以超过精度就会产生误差,从而会带来产生的结果接近但不等于想要的结果,而产生这种误差的又不是数的大小,而是数的精度问题。因此,我们在用浮点数要特别小心,我们可以通过java.math.BigDecimal 或者通过使用 long 类型来转换,这样可以做到精度不会出范围而避免的这种误差的产生。
、尾记

  这篇文章主要是我在达内学习期间,自己的发到征文的,然后还获得了二等奖,就此拿来纪念过去的时光。       此文绝对原创,全凭参考JDK外加自己总结。       谢谢您的参考!

转载于:https://www.cnblogs.com/snow1314/p/3618244.html

关于float的内部结构相关推荐

  1. float占几个字节_一个HashMap对象占多少字节?

    对象=对象头+成员变量+对齐填充 对象头结构:java对象在Heap里面的结构是这样的:对象头跟对象体,对象体跟C里面的结构体是一样的,对象头由两个域组成:用于存放hashcode.同步.GC的_ma ...

  2. float gpu 加速_Javascript如何实现GPU加速?

    一.什么是Javascript实现GPU加速? CPU与GPU设计目标不同,导致它们之间内部结构差异很大. CPU需要应对通用场景,内部结构非常复杂. 而GPU往往面向数据类型统一,且相互无依赖的计算 ...

  3. Pytorch:内部结构

    3.1.3 内部结构 tensor的数据结构如图3-1所示.tensor分为头信息区(Tensor)和存储区(Storage),信息区主要保存着tensor的形状(size).步长(stride).数 ...

  4. luajit开发文档wiki中文版(四) LuaJIT 内部结构

    2022年6月10日15:15:22 luajit开发文档中文版(一)下载和安装 luajit开发文档中文版(二)LuaJIT扩展 luajit开发文档中文版(三)FAQ 常见问题 luajit开发文 ...

  5. JVM8(4)java虚拟机内部结构

    JVM规范描述的是一种抽象化的虚拟机的行为,而不是任何一种广泛使用的虚拟机实现. 要去"正确地"实现一台Java虚拟机,其实并不像大多数人所想的那样高深和困难--只需要正确读取cl ...

  6. CPU 内部结构解析

    CPU 内部结构解析 为什么计算机能运行编写的代码(比如c语言,计算机为什么会运行这个东西,原理是什么)? 就目前理解,编辑的c语言最终加载到计算机的是二进制的数据,然后cpu 根据这些数据去进行相关 ...

  7. float a = 3.1; 显示警告的原因

    float a = 3.1;  会报错显示如下图所示 其实看提示也就知道原因了 java 默认带小数的为double 类型,所有我们需要转一下float 类型就行了 根据提示写的是这样 float a ...

  8. css float 的使用

    float float 属性定义元素在哪个方向浮动 left 元素向左浮动. right 元素向右浮动. none 默认值.元素不浮动,并会显示在其在文本中出现的位置. inherit 规定应该从父元 ...

  9. java float转换int

    1.Java的简单类型及其封装器类 ⑴Java简单类型与封装类 我们知道,Java语言是典型的支持面向对象的程序语言,但考虑到有些基本数据类型的结构简单,占内存小且存取速度快等优点,Java依然提供了 ...

最新文章

  1. win7硬件要求_电脑硬件运行游戏测评
  2. 2015.12.11-2015.12.13 金华旅程的学习计划
  3. 你们考试,我们都有点紧张呢…
  4. UOJ #150 【NOIP2015】 运输计划
  5. consulAPI服务的注册源码
  6. 35.FFmpeg+OpenGLES+OpenSLES播放器实现(九.OpenGLES播放视频)
  7. 转:Android应用开发性能优化完全分析
  8. BZOJ3529: [Sdoi2014]数表(莫比乌斯反演,离线)
  9. JAVA语言基础——类型转换
  10. OpenCV-车牌号检测
  11. java retainAll
  12. android expandablelistview横向,expandableListView 总结
  13. LeetCode 845——数组中的最长山脉
  14. 如何生成密钥文件Snk .
  15. linux网桥中stp分析,linux网桥中stp分析
  16. 网友抽中淘宝大奖,怎料小丑竟是自己
  17. 【iOS】XCode14 iOS16适配 pod签名 12.1闪退
  18. 《设计模式之禅》-策略模式
  19. 微步星辰的逆袭,专访微步星辰合伙人齐成岳
  20. 【二次开发】CityMaker常见分析——通视分析

热门文章

  1. 『不再迷茫 - 正则表达式』JS正则要点梳理 持续更新
  2. 联合光伏:雨后复斜阳 关山阵阵苍
  3. TMG 模拟公司网络架构要点
  4. windows server 2008 大量拷贝后释放内存
  5. C++中默认选中预编译头#includestdafx.h作用
  6. 硬编码是什么意思_饰品上那些编码和数字你都知道是什么意思吗?
  7. Flink SQL中的函数
  8. 大数据技术得发展方向如何
  9. 搭建大数据分析平台的必要性
  10. SQL语句新手练习(一)