浮点数(小数)在计算机中如何用二进制存储?

news2024/12/26 3:35:27

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/137182814
出自【进步*于辰的博客】

注:为了阐述更加严谨,本篇文章中将使用一些二进制的相关概念,出自上篇博文。

前言

在解析Float类的源码时,我对MAX_VALUE/MIN_VALUE的值很好奇,它们是怎么来的?于是利用我所知的二进制知识,尝试运算。一开工就发现没辙,因为我压根不知道小数的二进制是怎样表示、又是如何存储的。于是寻得一方案:

启发博文:浮点数(小数)在计算机中如何用二进制存储?(转发)。

这位博主的阐述专业且详细,下面我通过个人理解,尽量简明扼要地为大家阐明这个知识点。

正文

在开始之前,大家先看一张图。
在这里插入图片描述
Float 就是单精度,就是说 Float 变量由32位(4字节)二进制表示。现在大家对这张图有所疑惑,无妨,我要表达的意思是,小数的二进制由三部分组成,与整数完全不同。换言之,给我们一组小数的二进制,我们无法直接看出它的 真值 \color{green}{真值} 真值是多少。因此,需要使用一种纸面上的二进制数表现形式。

如何运算出这种纸面上的二进制数表现形式? \color{grey}{如何运算出这种纸面上的二进制数表现形式?} 如何运算出这种纸面上的二进制数表现形式?
所谓纸面上,就是一目了然,也就是使用整数二进制的表现形式去表现小数。那位博主是这样说的:

二进制转换为十进制的方法就是各个位的数字与位权乘积之和。

什么是“位权”?这张图给了答案。
在这里插入图片描述
就是底数的指数幂

答案很清楚了,可是如何运算浮点数的小数部分的二进制,难道使用如上“求和”的方法?当然可以,不过不太方便。

从另一位博主那儿“取经”得一方法:使用上图示例。整数部分照旧,是1011,将小数部分0.1875进行以下运算:

0.1875 * 2 = 0.37500
0.3750 * 2 = 0.75000
0.7500 * 2 = 1.50001
0.5000 * 2 = 1.00001

0011

结论:

将小数部分乘以2,取结果的整数部分,如此反复,直至结果为0,最后依次得到的整数部分就是小数部分的二进制。

PS:暂不懂其中原理,就挺好用。

补充一点 \color{red}{补充一点} 补充一点:那位博主将100个 float 类型的0.1相加,最终结果不是10.0
在这里插入图片描述
大家便可明了,无论二选一,0.1都是无限小数。无论单双精度,都无法表示完全,必然有所缺失或增加(四舍五入),故是10.000002

成功了一半,可1011.0011只是11.1875在纸面上的二进制数表现形式。

浮点数 ( 小数 ) 在计算机中如何用二进制存储? \color{grey}{浮点数(小数)在计算机中如何用二进制存储?} 浮点数(小数)在计算机中如何用二进制存储?
回到第一张图,小数的二进制由符号、指数、尾数三部分组成,这说明必然有一个公式,将这三部分进行运算,从而得到 真值 \color{green}{真值} 真值

公式是这样的:
在这里插入图片描述
二进制中基数(又称“底数”)是2,自然不必考虑。小数内部构造的三部分正好与图中三个未知变量对应,下面我一一剖析。(以单精度为例)

符号部分占1位,即0/1。(PS:小数没有 补码 \color{brown}{补码} 补码之说)

指数部分(8位)与尾数部分(23位)又是如何表示小数的?

我们来探讨一下,看到 m * ne 这样的公式,给你11.1875这个小数,你能想到哪些等式?

11.1875 = 111.875 * 10-1,m是111.875,n是10,e是 -1
11.1875 = 1.11875 * 101, m是1.11875,n是10,e是 1
......

有问题么?这里是二进制,n 是2,不是10,故等式不能这么写。

可是要满足如下等式,m 是多少?

11.1875 = m * 2-1
11.1875 = m * 21
......

看到这样的等式,大家是否似曾相识?没错,位运算,也就是这样:

11.1875 = m * 2-1 = m >> 1
11.1875 = m * 21 = m << 1
......

明白了么?

可这里有个问题,因为位运算移动的位数e是任意的,故 m 任意,则必然存在一个规范,用于限制e的值。

规范定义:

尾数部分用的是“将小数点前面的值固定为1的正则表达式”。
什么是正则表达式?按照特定的规则来表示数据的形式的表达式。

这样就清楚了,规范就是“将小数点左边第一位固定为1,其他为0”。如此,e就只有一个值。

PS:不过,对于那位博主将规范定义为“正则表达式”这一点,我的个人看法是,意思没错,可用词似乎不恰当,当时我就被误导了。当然,也可能是我的功底不扎实。

规范知道了,可尾数m是多少呢?大家在上文的阅读中有没有注意到一个细节?就是“纸面上的二进制数表现形式”那儿,我最后说了一句:“成功了一半”。成功在哪?又何出此言?

其实,小数在纸面上的二进制数表现形式就是 m * 2e 的结果。以11.1875为例:

11.18751011.0011

规范是“将小数点左边第一位固定为1,其他为0”,就是这样:

11.18751011.0011 = 1.0110011 << 3 = 1.0110011 * 23

这样,难道 m 是1.0110011?当然不是,那位博主已阐明:
在这里插入图片描述

因此,m 是01100110000000000000000。e 是3

对应到小数的内部构造,11.1875的二进制是:

0 00000011 01100110000000000000000

这是正确答案吗?还不是。

运用以上方法,我们来计算一下0.1875的二进制:

0.0011						原始数值
1.1							左移使个位为 1
1.10000000000000000000000	确保小数点后有2310000000000000000000000		仅保留小数点后的部分

得出,m 是10000000000000000000000,e 是-3

因此,0.1875的二进制是0 10000011 10000000000000000000000。(指数e使用的是“原码”,不是“补码”)

这样看来,似乎没有问题,可实际上指数部分还有点“门道”。

那位博主阐述道:

指数部分使用了 “ E X C E S S 系统表现” \color{green}{“EXCESS系统表现”} EXCESS系统表现

什么是“EXCESS系统表现”?那位博主已阐述得很清楚,我就不赘述了。

总结:

  • 11.1875的二进制是0 10000010 01100110000000000000000
  • 0.1875的二进制是0 01111100 10000000000000000000000

PS:

  1. 如果采用双精度,同理,只是二进制位数增加了而已。
  2. 那位博主运用 c++ 代码进行了验证,我把他提供的 code copy test 了一下,同样验证无误,只是目前我暂不知如何使用 java 进行验证,需要大家自行研究了。

本文完结。

上一篇:《二进制相关概念、运算与应用》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1559641.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【练习】滑动窗口思想

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;Java算法&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 1.长度最小的子数组 题目解析 讲解 代码实现 2.无…

微信小程序(黑马优购:登录)

1.点击结算进行条件判断 user.js //数据 state: () >({ // address: {} address: JSON.parse(uni.getStorageSync(address) || {}), token: }), my-settle.vue computed: { ...mapGetters(m_cart,[checkedCount,total,checkedGoodsAmount]), …

MySQL经验分享:Shell开发问题

背景 之前整理过Python连接使用MySQL的经验&#xff0c;链接如下&#xff1a; pymysql封装总结_pymysql封装类-CSDN博客 相比高级语言&#xff0c;Shell与MySQL开发使用相对会更麻烦一些&#xff1b;由于 shell是linux命令集的概称&#xff0c;是属于命令行的人机界面。Shel…

机器视觉学习(八)—— 阈值化

目录 一、阈值化 二、二值化和示例 2.1 二值化 2.2 示例代码 一、阈值化 OpenCV是一个开源的计算机视觉库&#xff0c;可以用于图像处理和计算机视觉任务。阈值化是图像处理中的一种常见操作&#xff0c;可以将图像的像素值分成两个或多个不同的类别&#xff0c;通常是黑色…

python统计分析——双样本均值比较

参考资料&#xff1a;python统计分析【托马斯】 1、配对样本t检验 在进行两组数据之间的比较时&#xff0c;有两种情况必须区分开。在第一种情况中&#xff0c;同一对象在不同时候的两个记录值进行相互比较。例如&#xff0c;用学生们进入初中时的身高和他们一年后的身高&…

wails 创建Go 项目

##wails是一个可以让go和web技术编写桌面应用#安装wails go install github.com/wailsapp/wails/v2/cmd/wailslatest#检查环境 wails doctor 创建项目wails init -n AuxiliaryTools -t vue-ts拉取go.mod的依赖项 go mod tidy进入 frontend 前端安装依赖项npm install /pnpm ins…

GitHub - 使用SSH进行连接(续)

文章目录 前言开发环境SSH源码获取SSH源码分析最后 前言 上篇文章中提出了存在一些默认密钥文件会被SSH自动添加的猜测&#xff0c;现在我们通过一些分析来验证这个猜测。 开发环境 MacOS: 14.3.1SSH: OpenSSH_9.4p1 SSH源码获取 该怎么验证这个猜测呢&#xff1f;有个方法…

QT初识(2)

QT初识&#xff08;2&#xff09; 创建好项目之后&#xff0c;多了些什么东西&#xff1f;main.cppwidget.hwidget.cppwidget.ui.pro项目工程文件 我们今天来继续了解QT。如果没看过上一次QT初识的小伙伴可以点击这里&#xff1a; https://blog.csdn.net/qq_67693066/article/d…

ADB(Android Debug Bridge)操作命令详解及示例

ADB&#xff08;Android Debug Bridge&#xff09;是一个强大的命令行工具&#xff0c;它是Android SDK的一部分&#xff0c;主要用于Android设备&#xff08;包括真实手机和平板电脑以及模拟器&#xff09;的调试、系统控制和应用程序部署。 下面是一些ADB的常用命令&#xff…

全国植被覆盖度VFC逐月数据/NDVI/净初级生产力NPP/植被类型​

引言 植被覆盖度是指植被&#xff08;包括叶、茎、枝&#xff09;在地面的垂直投影面积占统计区总面积的百分比。是刻画地表植被覆盖的一个重要参数, 也是指示生态环境变化的重要指标之一。 正文 数据简介 容易与植被覆盖度混淆的概念是植被盖度&#xff0c;植被盖度是指植被冠…

腾讯云轻量服务器8核16G服务器价格1668元一年送3个月,18M大带宽

腾讯云轻量应用服务器8核16G配置租用优惠价格1668元15个月&#xff0c;买一年送3个月&#xff0c;配置为&#xff1a;轻量8核16G18M、270GB SSD盘、3500GB月流量、18M带宽&#xff0c;腾讯云优惠活动 yunfuwuqiba.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云8核16G服务器…

复写零->C语言和JAVA版本的双指针解法

使用C语言和JAVA语言版本双指针来解决复写零问题 力扣链接:https://leetcode.cn/problems/duplicate-zeros/description/ 题意:对一个数组进行复写,遇到0写两遍,非0写一遍,复写结果不能超过原数组长度,即当复写结果达到数组长度时,后面的结果数组元素直接舍弃. 例子 思路:找到…

Spring Boot单元测试全指南:使用Mockito和AssertJ

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

机器学习每周挑战——旅游景点数据分析

数据的截图&#xff0c;数据的说明&#xff1a; # 字段 数据类型 # 城市 string # 名称 string # 星级 string # 评分 float # 价格 float # 销量 int # 省/市/区 string # 坐标 string # 简介 string # 是否免费 bool # 具体地址 string拿到数据…

SAP 学习笔记 - 系统移行业务 - Migration cockpit工具 - 移行Material(品目)

本章开始&#xff0c;来研究研究移行工具 Migration cockpit。 理论啥的先放一边&#xff0c;来先做一个简单的实例&#xff0c;以对 Migration cockpit 有个大概的印象。 这里就先做一个移行品目的例子。 1&#xff0c;LTMC 启动Migration cockpit工具 默认给我启动了 IE &a…

Python基础之pandas:Series和DataFrame定义及使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Series特点二、Series使用步骤1.Series定义2.索引和切片3.series的.get()4.掩码提取5.Series运算符和广播方法6.ufunc在Series对象中使用 三、DataFrame1.D…

使用python实现i茅台自动预约

使用python实现i茅台自动预约[仅限于学习&#xff0c;不可商用] 运行&#xff1a; 直接运行 imtApi.py 打包&#xff1a;切换到imt脚本目录&#xff0c;执行打包命令&#xff1a; pyinstaller --onefile imtApi.py这个应用程序可以帮助你进行茅台自动化配置。以下是一些使用…

【Laravel】06 数据库迁移工具migration

【Laravel】06 数据库迁移工具migration 1.migration文件目录2. 举例 1.migration文件目录 2. 举例 (base) ➜ example-app php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_crea…

Java基础学习: JDK动态代理

文章目录 一、什么是JDK动态代理二、JDK动态代理的特点三、JDK动态代理类如何使用四、JDK动态代理原理分析1、创建代理对象2、生成代理类 一、什么是JDK动态代理 JDK动态代理是Java提供的一种动态生成代理类和代理对象的技术。它主要利用Java的反射机制实现&#xff0c;在运行…

算法学习——LeetCode力扣动态规划篇10(583. 两个字符串的删除操作、72. 编辑距离、647. 回文子串、516. 最长回文子序列)

算法学习——LeetCode力扣动态规划篇10 583. 两个字符串的删除操作 583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 描述 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个…