float、double的精度,在内存中的存储方式

一、浮点型变量在内存中的存储方式

Java的浮点数遵循IEEE 754标准,采用二进制数据的科学计数法来表示浮点数,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。该标准中表示的浮点数表示分为规约形式和非规约形式以及特殊情况。

无论是单精度还是双精度在存储中都分为三个部分:

  1. 符号位(Sign) : 0代表正,1代表为负
  2. 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
  3. 尾数部分(Mantissa):尾数部分

根据IEEE 754 标准,对于float单精度,第 31 位(左边第1位)表示浮点数字的符号;第 30-23位(8位)表示指数(指数加完偏移量,即加偏移量127后的值);第 22-0 位是尾数(尾数是23位);存储方式如下图所示:

指数是有符号的,但并不是使用有符号整形(int)的存储方式,而是使用偏移(Offset)算法,存储的数据=元数据 + 127,所以【实际指数值 = 指数部分二进制值 - 127】。8位二进制能表示的范围为0~255,这样的话范围就是(-127~128),另外全0和全1作为特殊处理,所以指数部分能表示的范围为-126~127(规约形式)。可以参考https://www.zhihu.com/question/21711083

根据IEEE 754 标准,对于double双精度,第 63 位表示浮点数字的符号;第 62-52 位(11位)表示指数(指数加完偏移量);第 51-0 位是尾数(尾数是52位,尾数位比float多,尾数位越多,精度越高);双精度的存储方式为:

指数部分与float单精度存储方式一样使用偏移(Offset)算法,存储的数据=元数据 + 1023,所以【实际指数值 = 指数部分二进制值 - 1023】。11位二进制能表示的范围为0~2047,所以指数部分能表示的范围为-1022~1023。

非规约形式表示:

当指数部分全0而且小数部分不全0时表示的是非规格化的浮点数,因为这里默认没有前导1,而是0。

对于float类型,取值位0.f * 2-126,表示范围位 2-149~(1-2-23) × 2-126 这里没有考虑符号。(IEEE 754标准规定:非规约形式的浮点数的指数偏移值比规约形式的浮点数的指数偏移值小1。)

其他特殊表示:

1.当指数部分和小数部分全为0时,表示0值,有+0和-0之分(符号位决定),0x00000000表示正0,0x80000000表示负0.

2.指数部分全1,小数部分全0时,表示无穷大,有正无穷和负无穷,0x7f800000表示正无穷,0xff800000表示负无穷.

3.指数部分全1,小数部分不全0时,表示NaN,分为QNaN和SNaN,Java中都是NaN.

二、二进制的科学计数法

十进制的科学计数法:任何数字都可以表示成a×10n,其中1≤a<10,n表示整数,一般用于表示很大的数字,例如:623500000000可以表示为6.235×1011。同理,任何二进制都可以表示成a×2n,其中a为带小数点的二进制序列,且小数点在第二位,n表示整数,例如:100111101100000000000000可以表示为1.001111011×223

三、十进制转换为二进制

1.整数部分

余数法:用这个十进制的整数除以 2,会得到一个商值和一个余数值,再用商除以 2,一直除到商为 0 为止,把每次的余数,逆序连起来,就是要转的二进制数。整数总能用二进制准确表示。

2.小数部分

小数部分就是用十进制小数乘以2,得出的积,然后把积的整数位取出,再用积的小数部分乘以2,再把积的整数位取出,再用小数部分乘以2,循环操作,直到小数部分为0,或者遇到无限循环小数转换为二进制可能会损失精度),取到你认为足够精度的小数为止,然后把取出的整数位顺序连接起来,就是要转换成的二进制小数。

十进制

二进制

0.5

0.1

0.25

0.01

0.125

0.001

0.0625

0.0001

0.03125

0.00001

0.015625

0.000001

0.0078125

0.0000001

0.00390625

0.00000001

十进制 0.875 转换成二进制 0.111,十进制0.3转换成二进制0.01001100110011…。

四、二进制转换为十进制

float与double的二进制表示转换为十进制时,先表示为科学计数法,再分别转换小数部分和整数部分。

0 01111111 00000000000000000000000的指数部分为01111111=(27-1)-127 = 0,尾数部分为00000000000000000000000,(因整数部分总为1,所以存储时省略整数部分)该数的科学计数法表示为1. 00000000000000000000000×20,所以该二进制对应的十进制为1。

1 10000000 00000000000000000000000的指数部分为10000000 = 27-127 = 1,尾数部分为00000000000000000000000,该数的科学计数法表示为1.00000000000000000000000×21,左移1位变为10.0000000000000000000000,所以该二进制对应的十进制为2。

0 01111101 00110011001100110011001的指数部分为01111101 = 125 – 127 = -2,尾数部分为00110011001100110011100,该数的科学计数法表示为1.00110011001100110011100×2-2,右移2位变为0.0100110011001100110011001,整数部分为0,小数部分约为0.3,该数为0.3。

0 10000000 10010010000111111011011的指数部分为10000000 = 27 – 127 = 1,尾数部分为10010010000111111011011,该数的科学计数法表示为1.10010010000111111011011×21,左移1位变为11.0010010000111111011011,整数部分为3,小数部分约为0. 1415926,该数为3.1415926。

五、float、double的精度

数学领域中的精度一般指有效数字,是十进制位数, 而计算机中的精度通常是指二进制位数。

从上述几个float的二进制表示转换为十进制的示例可以看出:

  1. 指数位决定了范围大小,因为指数位表示的越大则表示的数值越大。
  2. 尾数位决定了计算精度,因为尾数位能表示的越大,则计算精度越大。

浮点数的精度决定于尾数部分,而float尾数占了23个二进制位,加上省略的整数部分的1,共24位决定浮点数的精度。24位二进制表示的最大数字为224转化为十进制数为 16,777,216(8个十进制位),因此有一种说法是float的十进制精度为8位,但是由于其并不能表示所有8位十进制数,因此也有种说法是其精度为7位。【这些说法都不准确,因为尾数部分包含整数部分和小数部分】准确的说,float可以保证7位十进制有效数字。

float能表示的最大数为0 11111110 11111111111111111111111,也是Float.MAX_VALUE的值,(224-1)× 2(127-23)约为3.4028235E38。

float能表示最小正数为1 00000000 00000000000000000000001(非规约表示),也是Float.MIN_VALUE的值,2-149约为1.4E-45

double位数占52位,加上省略的整数部分的1,共53位决定浮点数的精度。53位二进制表示的最大数字为253转化为十进制数为 9,007,199,254,740,992(16个十进制位),但是它不能表示所有16位十进制数,其精度介于15~16位。准确的说,double可以保证15位十进制有效数字。

Double表示的最大数为1.7976931348623157E308,最小正数为4.9E-324

六、浮点转二进制科学表示的代码实现

 1 import java.util.Scanner;
2 import java.util.regex.*;
3 public class FloatToHex {
4 /**
5 *将用户输入的浮点数,转换为二进制科学计数形式(浮点数在内存中的存储方式)
6 *@author: 李世颖
7 *@Create Date: 2020-01-10
8 */
9 public static void main(String[] args) {
10 // 键盘输入
11 Scanner sc = new Scanner(System.in);
12 String cmd=null;
13 float f = 0;
14 //double d = 0;
15 String binaryStr = "";
16 int prefixLen = 0;//需要补0位的数量
17 //float类型正则表达式规则
18 Pattern p = Pattern.compile("-?\\d+\\.?\\d*");
19 Matcher m = null;
20 //提示输入
21 System.out.println("输入浮点数,转换输出该浮点数的内存二进制表示形式。");
22 while (sc.hasNext()) {
23 //获取输入并删除分隔符
24 cmd = sc.nextLine();
25 //退出命令
26 if (cmd.equalsIgnoreCase("exit")) {
27 sc.close();
28 return;
29 }
30 //判断输入是否合法
31 m = p.matcher(cmd);
32 if (m.matches()) {
33 try {
34 f = Float.parseFloat(cmd);
35 //d = Double.parseDouble(cmd);
36 System.out.println(cmd + "在内存中的二进制表示如下:");
37 binaryStr = Integer.toBinaryString(Float.floatToIntBits(f));//将float转换为二进制字符串
38 //binaryStr = Long.toBinaryString(Double.doubleToLongBits(d));
39 prefixLen = 32 - binaryStr.length();
40 //prefixLen = 64 - binaryStr.length();
41 if(prefixLen > 0){
42 System.out.println(String.format("%0"+prefixLen+"d",0) + binaryStr);//补0后输出
43 }else{
44 System.out.println(binaryStr);
45 }
46 } catch (Exception e) {
47 System.out.println("输入的浮点数不合法或超出浮点数的范围");
48 continue;
49 }
50 } else {
51 System.out.println("请输入合法的浮点数");
52 }
53 }
54 }
55 }

float、double的精度、范围,在内存中的存储方式的更多相关文章

  1. Float在内存中的存储方式及IEC61131处理

    Float在内存中的存储方式及IEC61131处理 1,fp32(32bits float)类型数据在存储器中占用4Bytes存储,且遵循IEEE-754标准: 一个浮点数分三部分组成: 符号位s(1 ...

  2. <转载>浅谈C/C++的浮点数在内存中的存储方式

    C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中 ...

  3. C语言中浮点数在内存中的存储方式

    关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4. ...

  4. QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用

    FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QL ...

  5. 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)

    https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...

  6. float和double在内存中的存储方式

    本文转载于:http://wenku.baidu.com/link?url=ARfMiXVHCwCZJcqfA1gfeVkMOj9RkLlR9fIexbgs9gDdV8rIS48A1_xe1y6YgX ...

  7. C语言 float、double数据在内存中的存储方式

    float在内存中占4个字节(32bit),32bit=符号位(1bit)+指数位(8bit)+底数位(23bit) 指数部分 指数位占8bit,可以表示数值的范围是0-(表示0~255一共256个数 ...

  8. C/C++浮点数在内存中的存储方式

    一.内存表示 任何数据在内存中都是以二进制的形式存储的,浮点数的表示是把一个数的有效数字和数的范围在计算机的一个存储单元中分别予以表示,数的小数点位置随比例因子的不同而在一定范围内自由浮动.如下图是3 ...

  9. C/C++数据在内存中的存储方式

    目录 1 内存地址 2 内存空间   在学习C/C++编程语言时,免不了和内存打交道,在计算机中,我们存储有电影,文档,音乐等数据,这些数据在内存中是以什么形式存储的呢?下面做一下简单介绍. 本文是学 ...

  10. C++成员函数在内存中的存储方式

    用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间.按理说,如果用同一个类定义了10个对象,那么就需要分别为10个对象的数据和函数代码分 ...

随机推荐

  1. layui弹出层:使用icon图标小结

    转自:https://www.cnblogs.com/webSnow/p/15470350.html layui弹出层:使用icon图标小结 Layui 踩坑篇layui的弹框插件layer中,有很多 ...

  2. Android项目结构和文件间关联

    版本选择 Android 开发 SDK一般选择用最新的SDK版本, 这是Google官方建议的, App能运行的Android版本不是由SDK决定的, 是由每一个项目的minSDK决定的. SDK都是 ...

  3. TS内置类型与拓展

    TS内置类型与拓展 TypeScript具有类型系统,且是JavaScript的超集,其可以编译成普通的JavaScript代码,也就是说,其是带有类型检查的JavaScript. 内置类型 Type ...

  4. 斐讯K3C改散热

    斐讯K3C改散热 斐讯K3C日常使用还是不错的,就是日常的温度还是比较高的,不过冬天用来当暖手宝还是不错的. 这个改散热的方法是跟贴吧老哥学的,不得不说贴吧老哥还是牛皮,原贴在这,我当时拍的照片不够, ...

  5. Java I/O 教程(七) DataOutputStream和DataInputStream

    Java DataOutputStream Class Java DataOutputStream class 可以以机器无关方式往指定输出流写入Java原始数据类型,例如int, double, l ...

  6. 图片Base64编码解码的优缺点及应用场景分析

    随着互联网的迅猛发展,图片在网页和移动应用中的使用越来越广泛.而图片的传输和加载往往是网页性能的瓶颈之一.为了解决这一问题,图片Base64编码与解码技术应运而生.本文将介绍图片Base64相互转换的 ...

  7. 函数探秘:深入理解C语言函数,实现高效模块化编程

    欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. 函数的概念 在数学中我们就知道了函数这个概念,而C语言同样引入了函数这个概念,那C语 ...

  8. 如何快速使用LayUI MINI框架

    是什么 LayUI MINI是基于LayUI框架开发的一套最简洁.易用的后台框架模板,它已经是一个非常完整的脚手架,有现成的页面模板可以参考甚至是直接使用. 通常来说,如果我们准备开发一套管理系统的W ...

  9. [2023本地存储方案](https://www.cnblogs.com/fangchaoduan/p/17608006.html)

    2023本地存储方案 本地存储方案 cookie 本地存储:有期限的限制,可以自己设置过期期限.在期限内,不论页面刷新还是关闭,存储的信息都还会存在. localStorage 本地持久化存储:页面刷 ...

  10. pgrep查询当前运行程序的pid

    pgrep 运行的程序 [root@c1 ~]# pgrep matmul 2634730