浮点数在计算机中的二进制表示

news2024/11/22 13:25:26

文章目录

  • Part.I Introduction
  • Part.II 原理
  • Part.III 代码验证
  • Reference

Part.I Introduction

在这里插入图片描述

首先要了解一下下面的知识:

  • 1 位有两种状态:0 或 1
  • 1 字节(byte) = 8 位(bit)
  • 2 7 = 128 2^7=128 27=128 2 8 = 512 2^8=512 28=512 2 16 = 65536 2^{16}=65536 216=65536 2 32 = 4.3 × 1 0 9 2^{32}=4.3\times 10^{9} 232=4.3×109 2 63 = 9 × 1 0 18 2^{63}=9\times 10^{18} 263=9×1018 2 64 = 1.8 × 1 0 19 2^{64}=1.8\times 10^{19} 264=1.8×1019
  • float 在计算机中一般用 4 个字节存储,其表示范围为 [-3.4028235E38, 3.4028235E38],精确范围是[-340282346638528859811704183484516925440, 340282346638528859811704183484516925440]
  • int 在计算机中也是用 4 个字节存储的,它还不能表示小数,它的存储范围为 [-2147483648‬, 2147483647],一共是 2 32 = 4294967296 2^{32}=4294967296 232=4294967296 种可能,为什么 float 既能表示小数,并且其表示范围还那么大呢?因为间隔!int 的间隔固定为1,float 的间隔是不是等间距的,它在 0 的附近间距小,在远离 0 的位置间距大(实际上,因为某些原因,float 能精确表示的数还不足 2 32 = 4294967296 2^{32}=4294967296 232=42949672961)。
  • 上面提到,float 的间隔不是等间距的,在表示数据很大的时候,这个间隔有可能达到几百几千甚至更大,那么间隔中间的数怎么表示呢?就近原则,即在 float 『能表示的数』中寻找最接近『要表示的数』的数,那么就用这个数来表示『要表示的数』。比如,4294967244.0014294967295.009 均用 4294967296.000000 表示!
  • float 的精度为7,这句话的含义是 float 至少保证 7 位有效数字是准确的!

Part.II 原理

float 在计算机中一般是用 4 个字节进行存储的,也就是 32 位,其中第 1 位为符号位,第 2-9 位(共 8 位)用来表示指数,第 10-32(共 23 位)用来表示尾数。下图形象地表示了 float 各个位发挥的作用:
在这里插入图片描述
符号位很好理解,就是用 0 表示正数,用 1 表示负数;那么指数和尾数怎么理解呢?

首先我们知道常用的十进制科学计数法是将所有的数字转换成 ( ± ) a . b × 1 0 c (±)a.b \times 10^c (±)a.b×10c 的形式,其中 a 的范围是 1-9 共 9 个整数,b 是小数点后的所有数字,c 是 10 的指数。而计算机中存储的都是二进制数据,所以 float 存储的数字都要先转化成 ( ± ) a . b × 2 c (±)a.b \times 2^c (±)a.b×2c,由于二进制中最大的数字就是1,所以表示法可以写成 ( ± ) 1. b × 2 c (±)1.b \times 2^c (±)1.b×2c 的形式,float 要想存储小数就只需要存储 (±),b 和 c 就可以了。

所以上面将 32 位划分成了三块,第一块存储符号,第二块存储指数 c,第三块存储指数 b


举个例子,我们来表示8.25

  • 整数部分为 8,二进制表示为1000
  • 小数部分为 0.25,小数部分的二进制表示计算方法和整数部分的计算方法恰恰相反,整数部分转换二进制的时候是不断除以 2 得到的,这里就是不断乘以2:0.25*2 = 0.5,整数部分为0,记下:0;0.5*2 = 1.0,整数部分为1,记下:1,所以 0.25 的二进制表示即为 0.011*2^{-2}
  • 于是8.25的(伪)二进制表示为1000.01
  • 根据十进制的科学计数法,二进制的科学计数法可以进行如下类比:1000.01=1.00001*2^3
  • 基于上述,我们便可以直接写出8.25的二进制表示了。因为8.25是正数,所以符号位为0;指数为3(3+127=130),所以1000 0010(130的二进制表示);小数位为 00001,因为要用 23 位来表示它,所以需后补 0,所以0000 1000 0000 0000 0000 000
  • 所以8.25的二进制表示为0 1000 0010 0000 1000 0000 0000 0000 000

Part.III 代码验证

下面是一个大佬用 C 语言写的一个验证代码2

#include <stdio.h>
int main()
{
    float a = 1;
    unsigned int s, e, i;
    char b[33], c, d;
    while (a)
    {
        printf("输入一个浮点数(0退出):");
        scanf("%f", &a);
        s = e = *((int *)&a);           // 强制类型转换到无符号整数
        b[32] = 0;
        for (i = 32; i; i--, s /= 2)
            b[i - 1] = s % 2 + '0';     // 十进制二进制转换
        printf("内存:%f=%s\n", a, b);
        printf("符号:%c\n", b[0]);
        c = b[9];
        b[9] = 0;
        d = ((e & 0x7f800000) >> 23) - 127;
        printf("指数:%s   (浮点移动位数%d,>0右移,<0左移)\n", b + 1, d);
        b[9] = c;
        printf("尾数:%s   (不含最前面隐含1)\n小数:", b + 9);
        d++;
        b[8] = '1';
        for (i = 31; i > 9 && b[i] == '0'; i--)
            ;
        b[i + 1] = 0; // 消尾0
        if (b[0] == '1')
            printf("-"); // 负数
        if (d > 0) // 小数点浮动
        { // 小数点右移
            for (i = 0; i < d; i++)
                printf("%c", b[i + 8]);
            printf(".%s (手工转换为十进制方法是:小数点前乘2,小数点后除以2)\n\n", b + i + 8);
        }
        else
        { // 小数点左移
            printf("0.");
            for (; d; d++)
                printf("0");
            printf("%s (手工转换为十进制方法是:小数点前乘2,小数点后除以2)\n\n", b + 8);
        }
    }
}

下面是验证结果:

在这里插入图片描述

Reference


  1. float的精度和取值范围 ↩︎

  2. 如何利用c语言验证一个数的浮点表示? - lowxiong@知乎 ↩︎

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

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

相关文章

rhcsa简单的查询命令

时间 date -s "20021125 12:00:00" date 052312002002 一.简单语法 hwclock --查看硬件时间 hwclock --show 查看硬件时间 hwclock -w 同步硬件时间和系统时间 hwclock -s 将硬件时钟同步到系统时间 hwclock -r 查看当前时间 cal 查看当前月份日历 cal 10 …

nodejs+vue+elementui+express基于体质分析的个性化健身方案生成系统与设计

基于体质分析的个性化健身方案生成系统与设计 客户端&#xff1a; 1、在健身系统中可以自己选择课程&#xff08;需先充值&#xff0c;金额大于课程价格才可购买&#xff0c;否则提示余额不足&#xff0c;请充值&#xff09;&#xff0c;完成课程后由该课程的发布教练评价评分…

Python文件——使用Python读取txt文件

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注. 目录 一、文件的编码 1. 什么是编码 2. 常见的编码 二、P…

【软考】10.2 贪心法/回溯法/数据挖掘/智能优化

《贪心法》 适用于局部最优解 典型应用&#xff1a;背包问题 最有可能得到全局最优解&#xff1a;最大单位重量价值 ——> 重量 / 价值 《回溯法》 系统地搜索一个问题的所有解或者任一解深度优先&#xff0c;从根节点出发适用于解决迷宫类的问题 0-1背包算法的时间复杂度…

Python接口自动化之接口依赖!

以下主要介绍如何提取token、将token作为类属性全局调用及充值接口如何携带token进行请求。 一、场景说明 在面试接口自动化时&#xff0c;经常会问&#xff0c;其他接口调用的前提条件是当前用户必须是登录状态&#xff0c;如何处理接口依赖&#xff1f; 在此之前我们介绍过…

预训练机器阅读理解模型:对齐生成式预训练与判别式下游场景

©PaperWeekly 原创 作者 | 徐蔚文&#xff0c;李昕&#xff0c;邴立东等 单位 | 阿里巴巴达摩院 论文链接&#xff1a; https://arxiv.org/pdf/2212.04755.pdf 收录会议&#xff1a; NeurIPS 2023 论文链接&#xff1a; https://aclanthology.org/2023.acl-short.131.p…

038-第三代软件开发-简易视频播放器-自定义Slider (二)

第三代软件开发-简易视频播放器-自定义Slider (二) 文章目录 第三代软件开发-简易视频播放器-自定义Slider (二)项目介绍简易视频播放器自定义Slider (二)横向纵向 关键字&#xff1a; Qt、 Qml、 关键字3、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&…

进程(2)——进程状态(僵尸,睡眠……)【linux】

进程&#xff08;2&#xff09;——进程状态&#xff08;僵尸&#xff0c;睡眠……&#xff09;【linux】 一.操作系统的进程状态&#xff1a;1.1 运行态1.2 阻塞态1.3 挂起态 二.linux进程状态2.1 R——运行状态2.2 S——浅度睡眠状态2.3 D——&#xff08;disk sleep&#xf…

【数智化人物展】阿里元境CTO郭旷野:元宇宙技术推动数字内容生产变革

郭旷野 本文由阿里元境CTO郭旷野投递并参与《2023中国企业数智化转型升级先锋人物》榜单/奖项评选。 数据智能产业创新服务媒体 ——聚焦数智 改变商业 数字经济发展的大背景下&#xff0c;数字技术持续演进&#xff0c;逐渐形成了数字化生活、数字化生产模式&#xff0c;与此…

从工厂到社会:探索如何应用设计模式工厂模式

文章目录 &#x1f31f; 将设计模式工厂模式运用到社会当中&#x1f34a; 工厂模式在社会中的应用&#x1f389; 工厂&#x1f389; 餐厅&#x1f389; 运输 &#x1f34a; 工厂模式的优势&#x1f389; 代码简洁&#x1f389; 扩展性强&#x1f389; 便于维护和管理 &#x1f…

pytorch 笔记:KLDivLoss

1 介绍 对于具有相同形状的张量 ypred​ 和 ytrue&#xff08;ypred​ 是输入&#xff0c;ytrue​ 是目标&#xff09;&#xff0c;定义逐点KL散度为&#xff1a; 为了在计算时避免下溢问题&#xff0c;此KLDivLoss期望输入在对数空间中。如果log_targetTrue&#xff0c;则目标…

【继承练习题--多态-- 动态绑定-- 重写】

文章目录 继承的练习题&#xff1a;多态多态实现条件 动态绑定什么是重写Override 注解重写的条件&#xff08;缺一不可&#xff09;有一种特殊的重写&#xff1a;叫协变类型重写的设计原则快捷键生成重写重写和重载的区别object类是所有类的父类 总结 继承的练习题&#xff1a…

芯片封装简介【待补充】

TO封装 最开始的封装&#xff0c;这类封装三脚的比较多&#xff0c;比如7805 7812 等电源芯片 STO三脚贴片封装 TO的贴片形式 三极管和LDO比较常见 DIP封装 51单片机&#xff08;双列直插式封装&#xff09; SIP封装单列直插式封装&#xff08;罕见&#xff09; 5. SOP封…

出师表排序

一.原文件 二.代码 package org.example;import java.io.*; import java.util.ArrayList; import java.util.Collections; import java.util.List;public class day12 {public static void main(String[] args) {try (BufferedReader br new BufferedReader(new FileReader(…

Android 3D Launcher锁定IMU界面

故事背景&#xff1a; 最近工厂反馈由于VR设备老化测试完成之后&#xff0c;变绿界面不明显&#xff0c;只占3D系统一部分,每次需要戴头盔&#xff0c;才能确定老化完成。导致工厂效率变低&#xff0c;如果后期产能变大&#xff0c;效率更低。 1、针对以上需求我们需要拆分 1、…

动态规划-扫地机器人最少初始电量

扫地机器人在一个方格形状的地图中执行清扫任务&#xff0c;地图中每一个格子代表一个房间&#xff0c;地图用一个数组来表示&#xff1a; 1&#xff09;扫地机器人从地图左上角出发&#xff0c;每次清扫完一个房间后只能向石或向下走到另外一个房间&#xff0c;最后到达右下角…

LeetCode--196. 删除重复的电子邮箱

文章目录 1 题目描述2 解题思路2.1 代码实现 1 题目描述 表: Person ---------------------- | Column Name | Type | ---------------------- | id | int | | email | varchar | ----------------------id 是该表的主键列(具有唯一值的列)。 该表的每…

售货机相关的电路

一、货道选通矩阵电路&#xff0c;类似扫描电路&#xff0c;驱动哪个电机&#xff0c;就打开相应的行线与列线输出 二、MDB纸币器&#xff0c;虽然现在国内都是手机支付&#xff0c;但如果机器还是外销国外还是有用 三、硬币器电路&#xff0c;投币与退币&#xff0c;脉冲信号…

解决git action定时任务执行失败的方法

为了测试git action定时任务是否有效&#xff0c;你可能选择一个最近的时间测试&#xff0c; 但是发现怎么也触发不了&#xff0c;是不是觉得很苦恼。但是同样的时间&#xff0c;在第二天的定时任务又能成功运行。 这是什么原因&#xff1f; 原因就在上图&#xff0c;git act…

【算法|动态规划No.31 | 01背包问题】01背包模板题

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…