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

article/2025/10/29 7:58:45

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

前言

前面我有篇博文详解了二进制数,以及如何同二进制数表示整数。但是,计算机处理的不仅仅是整数,还有小数,同样小数在计算机也是用二进制进行存储的,但是,二进制如何去存储小数呢?计算机对于小数的计算又是否真的丝毫不差呢?本文将进行介绍。

一、用二进制表示小数

二进制转换为十进制的方法就是各个位的数字位权乘积之和。二进制数小数点前面部分的位权,第 1 位是 2 的 0 次幂、第 2 位 是 2 的 1 次幂……以此类推。小数点后面部分的位权,第 1 位是 2 的-1次幂、第2位是2的-2次幂。以此类推。0次幂前面的位的位权 按照 1 次幂、2 次幂……的方式递增,0 次幂以后的位的位权按照-1 次幂、-2次幂……的方式递减。这一规律并不仅限于二进制数,在十 进制数和十六进制数中也同样适用。
如把1011.0011这个有小数点的二进制数转换成十进制数过程如下:
在这里插入图片描述

二、计算机并不是永远准确的

我们可以很快算出,0.1累加100次后的结果是10,但是计算机算出来结果是10吗?实际上它计算出的结果是10.0000002

#include <stdio.h>void main(){ float sum;      
int i;
// 将保存总和的变量清 0    
sum = 0;
//0.1 相加 100 次   
for (i = 1;  i <= 100; i++) 
{        sum += 0.1f;
}
// 显示结果  
printf("%f\n", sum); }

在这里插入图片描述

  • 那么,这是为什么呢?计算机为什么会出错呢?道理也很简单,就如我们现实生活中使用的十进制数,有些数字我们也不能精确计算出来,比如1/3;同样,计算机用二进制表达数字,有些小数二进制也无法精确表达,比如十进制数0.1就无法用二进制数正确表达。

  • ,小数点后 4 位用二进制数表示时的数值范围为 0.0000~0.1111。因此,这里只能表示0.5、0.25、0.125、0.0625这四个 二进制数小数点后面的位权组合而成(相加总和)的小数。将这些数值 组合后能够表示的数值,如下表中所示的无序的十进制数。
    在这里插入图片描述

  • 由上表可见,十进制数0的下一位是0.0625。因此,这中间的小数, 就无法用小数点后4位数的二进制数来表示。同样,0.0625的下一位 数一下子变成了 0.125。这时,如果增加二进制数小数点后面的位 数,与其相对应的十进制数的个数也会增加,但不管增加多少位, 2 的-○○次幂怎么相加都无法得到0.1这个结果。实际上,十进制数 0.1 转换成二进制后,会变成 0.00011001100…(1100 循环)这样的 循 环小数 A。这和无法用十进制数来表示 1/3 是一样的道理。1/3 就是 0.3333…,同样是循环小数。

三、计算机中表示小数的二进制数是如何存储的呢?

像1011.0011这样带小数点的表现形式,完全是纸面上的二进制数 表现形式,在计算机内部是无法使用的。那么,实际上计算机是以什 么样的表现形式来处理小数的呢?

  • 很多编程语言中都提供了两种表示小数的数据类型,分别是双精度浮点数和单精度浮点数。双精度浮点数类型用64位、单精度浮点数类型用32位来表示全体小数。这些数据类型都采用浮点数 B 来表示小数。那么,浮点数究竟采用怎样的方式来表示小数 呢?

  • 浮点数是指用符号、尾数、基数和指数这四部分来表示的小数。
    在这里插入图片描述

  • 因为计算机内部使用的是二进制数,所以基数自然就是 2。因 此,实际的数据中往往不考虑基数,只用符号、尾数、指数这三部分 即可表示浮点数。也就是说,64位(双精度浮点数)和32位(单精度 浮点数)的数据,会被分为三部分来使用。
    在这里插入图片描述

符号部分、指数部分,尾数部分又是如何用二进制表达的呢?

  • 符号部分是指使用一个数据位来表示数值的符号。该数据位是1 时表示负,为0时则表示“正或者0”。这和用二进制数来表示整数时 的符号位是同样的。
  • 尾数部分用的是“将小数点前面 的值固定为1的正则表达式”
    **什么是正则表达式?**按照特定的规则来表示数据的形式即为正则表达式。是为了将小数的形式统一的一种规则,不然小数的表达形式太多了,计算机如何处理呢?就比如十进制的0.75如果没有规则,就会有无数种表达方式,如
    在这里插入图片描述
    因此,为了方便计算机处理,需要制定一个 统一的规则。例如,十进制数的浮点数应该遵循“小数点前面是0,小 数点后面第 1 位不能是 0”这样的规则。根据这个规则,0.75 就是 “0.75×10 的 0 次幂”,也就是说,只能用尾数部分是 0.75、指数部分 是0这个方法来表示。根据这个规则来表示小数的方式,就是正则表达式。
    同样的道理,二进制表示的小数,如果没有正则表达式(规则),那么也会有无数的形式。因此,我们使用的是“将小数点前面的值固定为1的正则表达 式”,来保证其形式的唯一。具体来讲,就是将二进制数表示的小数左移或右移(这里是逻辑 移位。因为符号位是独立的 B)数次后,整数部分的第1位变为1,第2位之后都变为0(这样是为了消除第2位以上的数位)。而且,第1位的 1在实际的数据中不保存。由于第1位必须是1,因此,省略该部分后就 节省了一个数据位,从而也就可以表示更多的数据范围(虽不算太多)。如二进制数1011.0011的尾数,根据正则表达式要变成如下形式进行保存。
    在这里插入图片描述
  • 指数部分用的则是“EXCESS系统表现
    EXCESS 系统表现是指,通过将指数部分表示范围的中间值设为0,使得负数不 需要用符号来表示。也就是说,当指数部分是 8 位单精度浮点数时, 最大值11111111 = 255的1/2,即01111111 = 127(小数部分舍弃)表示 的是0,指数部分是11位双精度浮点数时,11111111111 = 2047的1/2, 即01111111111 = 1023(小数部分舍弃)表示的是0。
    假设有这样一 个游戏,用1~13(A~K)的扑克牌来表示负数。这时,我们可以把中间的 7 这张牌当成 0。如果扑克牌 7 是 0,10 就表示+3,3 就表 示-4。事实上,这个规则说的就是EXCESS系统。

比如计算机是如何利用浮点数来表示十进制0.75的,我们可以通过代码进行验证

#include<stdio.h>
#include <STRING.H>void main()
{//单精度浮点数计算机中二进制的表示方法(1位表示符号+8位表示指数(正则表达式)+23位表示尾部(EXCESS系统法))float data; unsigned long buff;int i;char s[34];// 将 0.75 以单精度浮点数的形式存储在变量 date 中data=(float)0.75;// 把数据复制到 4 字节长度的整数变量 buff 中以逐个提取出每一位memcpy(&buff,&data,4);// 逐一提取出每一位for (i = 33; i >= 0; i--) {// 加入破折号来区分符号部分、指数部分和尾数部分if (i==1||i==10){s[i] = '-';}else{// 为各个字节赋值 '0' 或者 '1'if (buff % 2 == 1){s[i]='1';}else{s[i]='0';}buff/=2;}}s[34]='\0';printf("%s\n",s);
}

运行结果如下
在这里插入图片描述
这里,符号部分为0,指数部分为 01111110,尾数部分为 10000000000000000000000。因为 0.75 是 正数,所以符号位是 0。指数部分的 01111110 是十进制数 126,用 EXCESS系统表现就是- 1(126- 127 = - 1)。根据正则表达式的规则, 小数点前面的第1位是1,因此尾数部分10000000000000000000000实 际上表示的是1.10000000000000000000000这个二进制数。将尾数部分 的二进制数转换成十进制数,结果就是(1 × 2的0次幂)+(1 × 2的-1次幂) = 1.5。因此,0-01111110-10000000000000000000000这个单精度 浮点数,表示的就是“+ 1.5 × 2的-1次幂”。2的-1次幂是0.5,+ 1.5 × 0.5 = + 0.75。正好吻合,结果正确。

如何避免计算机计算出错?

有两种方法:
第一、回避策略,即无视这些错误。
第二、把小数转换成整数来计算。例如,将0.1相加 100 次这一计算,就可以转换为将 0.1 扩大 10 倍后再将 1 相加 100 次的计算,最后把结果除以10就可以了。


http://chatgpt.dhexx.cn/article/jSYX5sW4.shtml

相关文章

二进制小数的表示

二级制小数分为两大类&#xff1a;1、定点数&#xff1b;2、浮点数。 定点数 定点数&#xff1a; &#xff08;1&#xff09;小数点位置固定不变的数。 &#xff08;2&#xff09;定点数有定点整数和定点小数。 &#xff08;定点整数&#xff1a;小数部分为0&#xff1b;定点…

腾讯TDSQL全时态数据库系统论文入选VLDB

当地时间2019年8月26至30日&#xff0c;VLDB 2019会议在美国加利福尼亚召开&#xff0c;腾讯分布式数据库TDSQL与中国人民大学最新联合研究成果被VLDB 2019接收并将通过长文形式发表。VLDB是国际数据管理与数据库领域顶尖的学术会议之一&#xff0c;这是继去年腾讯TDSQL相似度计…

顶会VLDB‘22论文解读:CAE-ENSEMBLE算法

摘要&#xff1a;针对时间序列离群点检测问题&#xff0c;提出了基于CNN-AutoEncoder和集成学习的CAE-ENSEMBLE深度神经网络算法&#xff0c;并通过大量的实验证明CAE-ENSEMBLE算法能有效提高时间序列离群点检测的准确度与效率。 本文分享自华为云社区《VLDB22 CAE-ENSEMBLE论文…

【轨迹压缩】Trajectory Simplification: On Minimizing the Direction-based Error [2015] [VLDB]

一、一个动机 保护方向信息的方向保持轨迹简化&#xff08;DPTS&#xff09;已被证明表现良好&#xff0c;而现有关于 DPTS 的研究 要求用户指定一个容错&#xff0c;在某些情况下用户可能不知道如何正确设置&#xff08;例如&#xff0c;容错只能在未来某个时间知道&#xff…

VLDB 2021 EAB最佳论文:深度解析机器学习的基数估计为何无法实现?

©作者 | 曲昌博单位 | 西蒙菲莎大学近日&#xff0c;IEEE 数据工程新星奖王健楠团队论文《Are We Ready for Learned Cardinality Estimation?》夺得数据库顶会 VLDB 2021 年度的 EA&B 最佳论文奖。 数据库是企业管理和查询数据的复杂软件系统。 近年来随着机器学习以…

Transformers如何处理表格数据?【VLDB2022教程】Transformer表格数据表示:模型和应用...

来源&#xff1a;专知 本文为教程介绍&#xff0c;建议阅读5分钟最近的研究工作通过开发表格数据的神经表示扩展了语言模型。 在过去的几年中&#xff0c;自然语言处理界见证了基于transformer的语言模型(LM)在自由文本的神经表示方面的进展。鉴于关系表中可用知识的重要性&…

openGauss亮相VLDB2020,展示内存优化研究成果

VLDB&#xff08;Very Large Data Base&#xff09;作为数据库领域的三大顶级国际会议之一&#xff0c;是面向数据库研究人员&#xff0c;内核开发人员&#xff0c;开发商以及用户的年度国际会议论坛&#xff0c;代表数据库系统领域最杰出的研究和工程进展。在2020年&#xff0…

VLDB 2023 | 北大河图发布分布式训练神器Galvatron,一键实现大模型高效自动并行...

©作者 | 北京大学河图团队 单位 | 北京大学数据与智能实验室 北大河图团队提出了一套面向大模型的自动并行分布式训练系统 Galvatron&#xff0c;相比于现有工作在多样性、复杂性、实用性方面均具有显著优势&#xff0c;论文成果已经被 VLDB 2023 接收。 最近一段时间&…

利用 Map-Reduce 从文件中找到出现频率最高的 10 个 URL(2021 VLDB Summer School Lab0)

这篇博文主要是对 2021 VLDB Summer School Lab0 的一个总结 这个lab与MIT 6.824 的 lab1 相似&#xff0c;个人感觉比MIT 6.824 的 lab1 要稍微简单些&#xff0c;更容易上手。通过这个lab&#xff0c;可以学习到一些 Golang 的基础知识并对分布式系统有一个基础的了解&#…

Flink OLAP 助力 ByteHTAP 亮相数据库顶会 VLDB

复杂查询 QPS 破百&#xff0c;字节跳动 Flink OLAP 助力 ByteHTAP 亮相数据库顶会 VLDB。 2022 年 9 月 5 日至 9 月 9 日&#xff0c;VLDB 2022 在澳大利亚悉尼举行。字节跳动基础架构研究成果《ByteHTAP: ByteDance’s HTAP System with High Data Freshness and Strong Dat…

湖南大学计算机专业硕士研究导师,湖南大学研究生导师李睿科研论文被世界顶级数据库学术会议VLDB刊发...

李睿老师的论文被国际数据库顶级会议Very Large Data Bases接受并发表。 刊发的论文。 日前&#xff0c;以湖南大学信息科学与工程学院计算机科学系研究生导师李睿为第一作者&#xff0c;湖南大学为第一作者单位的科研论文“Fast Range Query Processing with Strong Privacy P…

PM-LSH: A Fast and Accurate LSH Framework for High-Dimensional Approximate NN Search(VLDB)

由于维数灾难的影响&#xff0c;高维空间中的最近邻(NN)搜索本质上是计算开销巨大的。局部敏感哈希(locality-sensitive hashing, LSH)是一种著名的近似神经网络搜索算法&#xff0c;能够以恒定概率在亚线性时间内回答c-近似神经网络(c-ANN)查询。现有的LSH方法主要基于哈希桶建…

Updatable Learned Index with Precise Positions(VLDB2022)

在现代数据库引擎中&#xff0c;索引在加速查询处理方面起着至关重要的作用。“学习索引”的新范式极大地改变了DBMS中索引结构的设计方式。关键的见解是&#xff0c;索引可以被视为预测数据集中查找键位置的学习模型。虽然这类研究在查找时间和索引大小方面都显示出良好的结果…

VLDB 2023 | 北大河图发布分布式训练神器Galvatron, 一键实现大模型高效自动并行...

关注公众号&#xff0c;发现CV技术之美 本文转自机器之心。 北大河图团队提出了一套面向大模型的自动并行分布式训练系统Galvatron&#xff0c;相比于现有工作在多样性、复杂性、实用性方面均具有显著优势&#xff0c;论文成果已经被 VLDB 2023 接收。 最近一段时间&#xff0c…

Benchmarking Learned Indexes(VLDB2021)

最近学习索引结构的进步建议用近似学习模型来替代现有的索引结构&#xff0c;比如b树。在这项工作中&#xff0c;我们提出了一个统一的基准&#xff0c;它将三种已经学习过的索引结构的优化实现与几种最先进的传统基准进行比较。通过使用四个真实的数据集&#xff0c;我们证明了…

阿里云数据库再获学术顶会认可,一文全览VLDB最新亮点

一年一度的数据库领域顶级会议VLDB 2019于当地时间8月26日-8月30日在洛杉矶圆满落幕。在本届大会上&#xff0c;阿里云数据库产品团队浓墨登场&#xff0c;不仅有多篇论文入选Research Track和Industrial Track&#xff0c;为了进一步加深产学研学术交流&#xff0c;阿里云还在…

2019计算机研究生暑期学校,2019年度VLDB暑期学校

由CCF数据库专业委员会、VLDB中国数据库学院主办&#xff0c;中国人民大学信息学院与数据工程与知识工程教育部重点实验室承办的2019年度VLDB暑期学校(VLDB Summer School 2019)于2019年7月22日在中国人民大学信息楼报告厅隆重举行开班仪式。出席开班仪式的嘉宾有&#xff1a;中…

13 种高维向量检索算法全解析!数据库顶会 VLDB 2021 论文作者干货分享

编者按&#xff1a; 以图搜图、商品推荐、社交推荐等社会场景中潜藏了大量非结构化数据&#xff0c;这些数据被工程师们表达为具有隐式语义的高维向量。为了更好应对高维向量检索这一关键问题&#xff0c;杭州电子科技大学计算机专业硕士王梦召等人探索并实现了「效率和精度最…

Deep Upsupervised Cardinality Estimation 解读(2019 VLDB)

Deep Upsupervised Cardinality Estimation 解读&#xff08;2019 VLDB&#xff09; Deep Upsupervised Cardinality Estimation选择度&#xff08;基数&#xff09;估计问题定义选择度和数据联合分布的关系深度自回归模型如何计算joint distribution编码解码策略具体执行属性的…

VLDB 2021 COCO 论文阅读

Epoch-based Commit and Replication in Distributed OLTP Databases 记录一篇之前读过的论文。。。 整篇论文的核心在于Epoch&#xff0c;将传统数据库以事务为粒度提交和恢复变成了以Epoch为粒度来提交和恢复&#xff0c;这样做的好处就是可以减少2PC和同步复制的时间开销。…