计算机如何存储浮点数

浮点数组成

在计算机中浮点数通常由三部分组成:符号位、指数位、尾数位。IEEE-754中32位浮点数如下:
32bit浮点数组成
上图32bit浮点数包含1bit的符号位,8比特的指数位和23bit的尾数位。对于一个常规浮点数,我们来看看它是如何存储和计算的。这里以浮点数25.125为例。这个浮点数分为整数(25(d))和小数部分(0.125(d)),(下面25(d)中d表示十进制,后续b表示二进制)
于是:
25 ( d ) = 11001 ( b ) 0.125 ( d ) = 0.001 ( b ) 25.125 ( d ) = 11001.001 ( b ) = 1.1001001 E 4 ( b ) \begin{align*} 25(d)&=11001(b)\\ 0.125(d)&=0.001(b)\\ 25.125(d)&=11001.001(b)=1.1001001E^{4}(b) \end{align*} 25(d)0.125(d)25.125(d)=11001(b)=0.001(b)=11001.001(b)=1.1001001E4(b)
明显这个数是一个正数,所以我们可以得知符号位S=0。指数位的计算和我们想象的稍微有点区别,这里我们的2禁止指数位是4。在十几种考虑的指数位可能是负数,为了避免负数情况,我们可以将指数表达范围移动一个偏置到正数区域。因为我们的指数位位8bit,有符号整数最高能表示 2 7 − 1 = 127 2^7-1=127 271=127,所以对指数位偏移一个127即可得到正数。所以我们的指数位部分为: 4 ( d ) + 127 ( d ) = 131 ( d ) = 10000011 ( b ) 4(d)+127(d)=131(d)=10000011(b) 4(d)+127(d)=131(d)=10000011(b)。接下来是尾数,因为 25.125 ( d ) = 11001.001 ( b ) 可以为 1.1001001 E 4 ( b ) 也可以为 . 11001001 E 5 ( b ) 25.125(d)=11001.001(b)可以为1.1001001E^{4}(b)也可以为.11001001E^{5}(b) 25.125(d)=11001.001(b)可以为1.1001001E4(b)也可以为.11001001E5(b)这样我们就得到了不同的表示方法。为了确保总是用相同的方法表示浮点数,IEEE-754中要求了表示尾数的部分总是为1.xxx。正因如此,我们这里的指数部分才是4而不是5。也正是因为如此,所以我们只需要保存.xxx即可,因为小数点前一定是1,这样能节省一个bit。尾数部分为1001001,这样我们的浮点数在内存中表示为:01000001110010010000000000000000。这个值如果是32有符号的定点数int32他应该表示的为:1103691776。
0 10000011 10010010000000000000000

代码验证

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <limits>using namespace std;
// 定义一个联合体用于访问浮点数的内存表示
union FloatBits {float f;uint32_t bits;
};// 打印浮点数的二进制表示
void printFloatBits(float value) {FloatBits fb;fb.f = value;std::cout << "Float value: " << std::fixed << std::setprecision(6) << value<< std::endl;std::cout << "Binary representation: ";// 从最高位开始逐位打印for (int i = 31; i >= 0; --i) {// 通过位掩码检查每一位的值uint32_t mask = 1 << i;std::cout << ((fb.bits & mask) ? '1' : '0');// 在输出中添加空格分组if (i % 8 == 0)std::cout << ' ';}std::cout << std::endl;
}int main() {float number = 25.125f;int a = 1103691776;float *b = reinterpret_cast<float *>(&a);int zp = 0;            // 00000000000000000000000000000000int zn = -2147483648;  // 10000000000000000000000000000000int infn = -8388608;   // 11111111100000000000000000000000int infp = 2139095040; // 01111111100000000000000000000000int nan = 2139095041;  // 01111111100000000000000000000001float inf_float = -std::numeric_limits<float>::infinity();std::cout << "-inf float for int  " << *reinterpret_cast<int *>(&inf_float)<< " -inf float = " << inf_float << "\n";float *zero_pos = reinterpret_cast<float *>(&zp);float *zero_neg = reinterpret_cast<float *>(&zn);float *infn_f = reinterpret_cast<float *>(&infn);float *infp_f = reinterpret_cast<float *>(&infp);float *nan_f = reinterpret_cast<float *>(&nan);printFloatBits(number);std::cout << "a = " << a << " *b = " << *b << " number = " << number<< " +0 => " << *zero_pos << " -0 =>" << *zero_neg << " +inf => "<< *infp_f << " -inf => " << *infn_f << " nan => " << *nan_f<< "\n";return 0;
}

使用GDB验证存储变量:
在这里插入图片描述

x/4tb:

  • 4 :表示4个后面的元素
  • t:表示打印为二进制
  • b:打印单位为byte(8bit)。

你可能会感到疑惑为什么这个值看起来和我们的结果不太一样,这是因为我们的机器使用小端存储法。show endian可以打印当前运行机器上是大端存储还是小端存储法。实际的二进制按照高位字节存储在低位的方式存储。所以这个值作为二进制,我们应该反向理解为:0100000 111001001 00000000 00000000。同理你可以试一试打印变量a,你就会发现两着结果完全相同。尽管二进制上完全相同,但是因为用了不同的类型符修饰运算的时候依然能知道这个数是表示浮点数的25.125还是无符号整数的1103691776。

浮点数的特殊值

  1. E不全为0或不全为1。这时,浮点数就采用偏置表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
  2. E全为0。这时,浮点数的指数E等于1-127(或者1-1023(64bit)),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
  3. E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)(111111111000000000000000000000000(b))

如何计算负数的二进制

  1. 找到对应的正数(8388608),计算二进制(00000000100000000000000000000000)。
  2. 反转所有位,得到二进制的反码(11111111011111111111111111111111)。
  3. 反码+1得到二进制的补码(111111111000000000000000000000000)。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库系统原理 | 查询作业2

整理自博主本科《数据库系统原理》专业课自己完成的实验课查询作业&#xff0c;以便各位学习数据库系统概论的小伙伴们参考、学习。 *文中若存在书写不合理的地方&#xff0c;欢迎各位斧正。 专业课本&#xff1a; ​ ​ ———— 本次实验使用到的图形化工具&#xff1a;Heidi…

CTF常用sql注入(一)联合注入和宽字节

0x01 前言 给自己总结一下sql注入的常用姿势吧&#xff0c;记录一下学习 0x02 联合 联合注入的关键词是union SQL的union联合注入原理是联合两个表进行注入攻击&#xff0c;使用union select关键词来进行联合查询。 那么为什么我们在题目中一般是只写一个呢 因为 $sql &quo…

SwiftData 模型对象的多个实例在 SwiftUI 中不能及时同步的解决

概览 我们已经知道,用 CoreData 在背后默默支持的 SwiftUI 视图在使用 @FetchRequest 来查询托管对象集合时,若查询结果中的托管对象在别处被改变将不会在 FetchedResults 中得到及时的刷新。 那么这一“囧境”在 SwiftData 里是否也会“卷土重来”呢?空说无益,就让我们在…

redis 如何使用 scan, go语言

建议用方案乙 文章目录 场景方案方案甲方案乙 拓展 场景 redis 中存在大量 key。 其中有一部分是用户登陆的 session_id&#xff0c; 结构是 &#xff1a; session_id:1session_id:2session_id:3需求&#xff1a; 有多少用户在线 方案 方案甲 keys session_id:*这种方式简…

FlinkSQL 开发经验分享

作者&#xff1a;汤包 最近做了几个实时数据开发需求&#xff0c;也不可避免地在使用 Flink 的过程中遇到了一些问题&#xff0c;比如数据倾斜导致的反压、interval join、开窗导致的水位线失效等问题&#xff0c;通过思考并解决这些问题&#xff0c;加深了我对 Flink 原理与机…

华为云简介

前言 华为云是华为的云服务品牌&#xff0c;将华为30多年在ICT领域的技术积累和产品解决方案开放给客户&#xff0c;致力于提供稳定可靠、安全可信、可持续创新的云服务&#xff0c;赋能应用、使能数据、做智能世界的“黑土地”&#xff0c;推进实现“用得起、用得好、用得放心…

鸿蒙应用笔记

安装就跳过了&#xff0c;一直点点就可以了 配置跳过&#xff0c;就自动下了点东西。 鸿蒙那个下载要12g个内存&#xff0c;大的有点吓人。 里面跟idea没区别 模拟器或者真机运行 真机要鸿蒙4.0&#xff0c;就可以实机调试 直接在手机里面跑&#xff0c;这个牛逼&#xf…

深度学习与CV入门

文章目录 前言历史 前言 历史 tensorflow可以安装Tensorboard第三方库用于展示效果 TensorFlow工作流程&#xff1a;p6-4:20 使用tf.data加载数据。使用tf.data实例化读取训练数据和测试数据模型的建立与调试:使用动态图模式Eager Execution和著名的神经网络高层API框架Ker…

[笔记] 卷积 - 02 滤波器在时域的等效形式

1.讨论 这里主要对时域和频域的卷积运算的特征做了讨论&#xff0c;特别是狄拉克函数的物理意义。 关于狄拉克函数&#xff0c;参考这个帖子&#xff1a;https://zhuanlan.zhihu.com/p/345809392 1.狄拉克函数提到的好函数的基本特征是能够快速衰减&#xff0c;对吧&#xf…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【17】认证服务01—短信/邮件/异常/MD5

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【17】认证服务01 环境搭建验证码倒计时短信服务邮件服务验证码短信形式&#xff1a;邮件形式&#xff1a; 异常机制MD5参考 环境搭建 C:\Windows\System32\drivers\etc\hosts 192.168.…

HackTheBox----Editorial

Editorial 测试过程 1 信息收集 NMAP端口扫描 nmap -sC -sV 10.10.11.20服务器开启了 22、80 端口 80 端口测试 服务器只开启了 22 和 80 端口&#xff0c;先从 80 端口开始进行测试 echo "10.10.11.20 editorial.htb" | sudo tee -a /etc/hostspublish with us…

Scrapy框架的基本使用教程

1、创建scrapy项目 首先在自己的跟目录文件下执行命令&#xff1a; PS D:\BCprogram\python_pro\bigdata> scrapy startproject theridion_grallatorscrapy startproject 项目名 具体执行操作如下&#xff1a;1、创建项目目录&#xff1a;Scrapy会在当前工作目录下创建一…

001,函数指针是一种特殊的指针,它指向的是一个函数地址,可以存储函数并作为参数传递,也可以用于动态绑定和回调函数

函数指针是一种特殊的指针 001&#xff0c;函数指针是一种特殊的指针&#xff0c;它指向的是一个函数地址&#xff0c;可以存储函数并作为参数传递&#xff0c;也可以用于动态绑定和回调函数 文章目录 函数指针是一种特殊的指针前言总结 前言 这是ai回答的标准答案 下面我们…

bash条件判断基础adsawq1`1nn

判断的作用 判断后续操作的提前条件是否满足如果满足执行一种命令不满足则执行另一种指令 条件测试类型&#xff1a; 整型测试字符测试文字测试 整数测试&#xff1a;比较两个整数谁大谁小&#xff0c;是否相等&#xff1b; 二元测试&#xff1a; num1 操作符 num2 -eq: 等于…

Alt与Tab切换窗口时将Edge多个标签页作为一个整体参与切换的方法

本文介绍在Windows电脑中&#xff0c;使用Alt与Tab切换窗口时&#xff0c;将Edge浏览器作为一个整体参与切换&#xff0c;而不是其中若干个页面参与切换的方法。 最近&#xff0c;需要将主要使用的浏览器由原本的Chrome换为Edge&#xff1b;但是&#xff0c;在更换后发现&#…

基于RK3588的8路摄像头实时全景拼接

基于RK3588的8路摄像头实时全景拼接 输入&#xff1a;2路csi转8路mpi的ahd摄像头&#xff0c;分辨率1920 * 1080 8路拼接结果&#xff1a; 6路拼接结果&#xff1a; UI界面&#xff1a; UI节目设计原理

Lua、AB包热更新总结

1.AB包热更新 &#xff08;1&#xff09;AB包是一种特定的压缩文件&#xff0c;可以放模型贴图音效等等 &#xff08;2&#xff09;Resources目录下打包时只读 无法修改&#xff1b;而AB包存储的位置是自定义的&#xff0c;能够动态更新&#xff0c;同时可以决定资源包初始的大…

huggingface笔记:gpt2

0 使用的tips GPT-2是一个具有绝对位置嵌入的模型&#xff0c;因此通常建议在输入的右侧而不是左侧填充GPT-2是通过因果语言建模&#xff08;CLM&#xff09;目标进行训练的&#xff0c;因此在预测序列中的下一个标记方面非常强大 利用这一特性&#xff0c;GPT-2可以生成语法连…

人工智能时代打工人摸鱼秘籍(1)- 为啥说大模型像人?

人工智能以势不可挡的方式席卷全球。 所有公司&#xff0c;都在削尖脑袋想&#xff0c;如何在在产品、营销、运营、服务和管理上加持大人工智能的能力。 公司在卷生卷死的时候&#xff0c;有一批人已经偷偷在用大模型提&#xff08;摸&#xff09;效&#xff08;鱼&#xff09;…

昇思25天学习打卡营第1天|初识MindSpore

# 打卡 day1 目录 # 打卡 day1 初识MindSpore 昇思 MindSpore 是什么&#xff1f; 昇思 MindSpore 优势|特点 昇思 MindSpore 不足 官方生态学习地址 初识MindSpore 昇思 MindSpore 是什么&#xff1f; 昇思MindSpore 是全场景深度学习架构&#xff0c;为开发者提供了全…