problem b: 十进制整数转二进制_二进制的科学计数法?白话谈谈计算机如何存储与理解小数:IEEE 754...

a0853e9c696ab7b8ad01e55db51d1828.gif

浮点数的计算机表示(IEEE 754),由 UCB 数学教授 William Kahan 主要起草。后者也因其卓越贡献于1989年获得图灵奖。计算机组成原理与汇编语言这两门课均对该内容有所讲解。与课程中直接抛出公式与概念不同,我想首先与各位探讨"科学计数法"这个概念,进而讨论设计二进制的科学计数法需要涉及到哪些元素。接着,我们讨论如何在内存上表达这个方案。最后讨论计算机的具体实现。

科学计数法

我们都了解科学计数法。科学计数法的精妙之处在于,其将"量级"与"数值"两个信息拆分,让使用者对这两个信息更加明确。

如上,我们可以将任何有理数拆分成的形式。值得注意的是:

  • 的取值范围是
  • 一定是一个整数

对于任何有理数,我们都可以用两个范围狭小(规则明确)的数字 B 与 C 来表示。

此外,我们知道,十进制只不过是记录数字大小的一种方式而已。历史上出现过的二进制、三进制、二十进制,都可以毫无障碍地表示数字,并且还有其独具的数学特性。

那么,二进制可以用科学计数法表示吗?答案当然是肯定的。

二进制的科学计数法

注意,这里下标2,代表这个数是二进制。 同理,对应十进制中的数字。

通过观察十进制的科学计数法形式,对于二进制,我们自然可以做出如下约定:

  • 的取值范围是
  • 一定是一个整数

这里我们补充说明一下,二进制的小数是什么样的。对于 这个十进制数,如果要将其转换为二进制:

  • 将其整数部分与小树部分分开;
  • 对于整数部分 5 ,我们使用"不断除以2取余数"的方法,得到 101 ;
  • 对于小数部分 .25 ,我们使用"不断乘以2取整数"的方法,得到 .01

关于进制转换的具体方法与背后的数学原理,我写过一篇文章进行讨论,见这里:十进制转二进制 / 八进制 / 十六进制的手算方法,及其数学原理的通俗解释。

这里,我们只需要明确,二进制是存在小数形式的,且可以表示一切十进制可表示的数(的近似)。

计算机如何记录二进制的科学计数法

接着,我们步入正题:只会表示0/1的计算机,如何记录并表达浮点数呢?

给一个32位的空间,如果不做任何约束,我们只能将其理解为一个整数,并且其取值范围为 。

这是因为,计算机只能记录 0 和 1 这两个信息,并不能直接记录小数点点在哪里。因此,我们需要设置一定规则,取出一定位,用于表示小数点点在哪里。这必将牺牲一定的精度与取值范围。

因此,我们将这 32 位空间分为三部分:

  • 第一部分,用于表示精度,即这个数字值是多少,对应上面的B;
  • 第二部分,用于表示小数点,即量级,对应上面的C;
  • 第三部分,用于表示正负,只需要使用1位。

在 IEEE 754 中,我们分别将上述一、二、三部分叫做尾数M阶码E符号s3b6cd5b6f89cd1738901edf2f9fe6692.png于是我们有了二进制的表达式:

为了表示尽可能多的、常用的小数,我们有如下需求

  • 对于符号位 s ,如果该位上是 0 ,则为正数;为 1 ,则为负数。
  • 对于尾数 M ,其取值范围为 ;
  • 对于阶码 E ,其为一个整数,并且取值范围应该包含负数、0、正数。

可以注意到,对于 M 、 E ,我们并不能直接用二进制表示,还需要设定一定规则。

尾数 M

假设尾数 M 一共有 f 位,则 f 可表示的整数取值范围为 ,我们称 f 直接对应的非负整数为 C 。为了将其投影到 ,我们做出如下变换:

解码 E

假设解码 E 一共有 e 位,则 e 可表示的整数取值范围为 ,我们称 e 直接对应的非负整数为 Exp 。我们希望 E 可以取到负数,因此做出如下变换:

这样,我们的 E 取值范围就来到了 。

总结

有了如上设计的规则,我们便知晓了计算机记录浮点数的方式,以及转换流程。以下图为例。

53ec6e45c4ebda035ce88f21d49f11b3.png
二进制转换到其对应的十进制数0.15625过程

知识点与例题

上面我们讨论了 IEEE 754 的思想,但是并不严谨,比如:

  • 正负无穷该怎么表达?
  • 如此表示会不会造成空间的浪费?
  • ...

因此,我们从数学上严谨地讨论一道例题,考虑一下规格化浮点数。例题源自我的汇编语言笔记。

题目

给定一个浮点格式(IEEE 754),有k位指数和n位小数,对于下列数,写出阶码E、尾数M、小数f和值V的公式。另外,请描述其位表示。

  • 数5.0;
  • 能够被准确描述的最大奇数;
  • 最小的正规格化数。

解决

前置知识一:IEEE 754

IEEE 754约定,计算机中浮点数二进制表示为:

数字形式:

  • 符号:s
  • 尾数:M,是一个位于区间[1.0, 2.0)内的小数
  • 阶码:E

编码形式:

exp域:E(注意,E要进行变换,再存储在exp中); frac域:M。

前置知识二:规格化浮点数(Normalized)

这里讨论到规格化浮点数(Normalized):

  • 满足条件:exp不全为0且不全为1。
  • 真实的阶码值需要减去一个偏置(biased)量:
    • 单精度数:127(Exp:1...254,E:-126...127)
    • 双精度数:1023(Exp:1...2046,E:-1022...1023)
    • ,e = exp的域的位数
    • E = Exp - Bias
    • Exp:exp域所表示的无符号数值
    • Bias的取值:
  • frac的第一位隐含1:M = 1.xxx...x_2
    • 因此第一位的“1”可以省去,xxx...x:bits of frac
    • Minimum when 000...0 ()
    • Maximum when 111...1 ()
前置工作一:整理变量关系

则E为

E最大值为。(为什么不是呢?因为有规定:exp全部取1为“非规格化浮点数”,因此规格化浮点数中exp不能全部取1,顶多为(1)*(0))

E的最小值为。(为什么不是呢?因为有规定:exp全部取0为“非规格化浮点数”,因此规格化浮点数中exp不能全部取0,顶多为(0)*(1))

前置工作二:总结特性

抛开例题,来看一个例子:

  • 8位浮点数表示:exp域宽度为4 bits,frac域宽度为3 bits。则,其偏置量的值为2^(4-1) - 1 = 7.
  • 其他规则符合IEEE 754规范。

取值范围如下表。

sexpfracEvalue
00000000-60
00000001-61/8 * 1/64 = 1/512
00000010-62/8 * 1/64 = 2/512
...
00000110-66/8 * 1/64 = 6/512
00000111-67/8 * 1/64 = 7/512
00001000-68/8 * 1/64 = 8/512
00001001-69/8 * 1/64 = 9/512
...
00110110-114/8 * 1/2 = 14/16
00110111-115/8 * 1/2 = 15/16
0011100008/8 * 1 = 1
0011100109/8 * 1 = 9/8
00111010010/8 * 1 = 10/8
...
01110110714/8 * 128 = 224
01110111715/8 * 128 = 240
01111000n/ainf

可以看出,假设frac有f位,则M可视为:

其中,C是整数,由frac决定,即;

并且C满足。

则浮点数V的十进制即为:

也可写作:

其中,、分别为exp、frac位数,为常数。

解决问题一:数0.5

较为简单,直接解决如下。

0.5   

则,位的描述为:

sexpfrac
0bin(-1 + (2^(e-1) - 1))00....(共n位)
解决问题二:能够被准确描述的最大奇数

根据前置工作二,可以看出,对于规格化浮点数可化简为:

现在的任务有两个:

  • 是整数,不能有小数(则应大于等于);
  • 是奇数(不是奇数,因此使为奇数,则取1,则取)。

下面分类讨论:

情况一:E可以取到f时,

即时,

取,取其能取的最大奇数,对应的二进制为: exp:dec2bin(),frac:1*(frac全为1)

情况二:E取不到f时,

这种情况不可能,因为E取不到f,则很多整数都不能表示。

解决问题三:最小的正规格化数

观察:

则取,、分别取最小。

由前置工作一,取,取,对应的二进制为: exp:0*1,frac:0*

后记:我第一学习浮点数是在2019年年末,当时对于浮点数的笔记和理解是有问题的。在此感谢一位湖南大学的朋友(公众号 / CSDN:梓酥),给我发邮件,指出我的问题~

感谢你读到最后!我是小拍,一名计算机技术爱好者!觉得文章不错的话,可以点击“在看”支持我一下!有任何批评建议或者合作事宜,可以给我发邮件 piperliu@qq.com ,或者关注公众Piper蛋窝,回复「微信」来加我微信联系~

1d2f4e22493774b5587803397247e01d.gif

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

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

相关文章

分享我的写作经验

大家好,我是Z哥。最近一段时间,我面基了几个在微信上聊得不错的小伙伴。和其中的两位有聊到关于写作的事情。概括地说就是他们也想写写博客、公众号,但是感觉无从下手。我和他们分享了我的一些经验,在这里做一下总结和补充&#x…

数据结构——二叉树的最小深度算法

给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明:叶子节点是指没有子节点的节点。 输入:root [3,9,20,null,null,15,7] 输出:2 示例 2: 输入:root …

开发板实现645协议C语言,迅为-imx6ull开发板之C语言实现LED例程

第九章我们使用汇编编写了 LED 灯的实验,在实际开发过程中大部分还是使用 C 语言,汇编只是用来完成 C 语言环境的初始化,本章我么就来实现用汇编完成 C 语言环境的初始化,然后用 C 语言实现 LED 的例程。10.1 C 程序版LED例程简介…

解锁环境变量在云原生应用中的各种姿势

应用程序在某些时刻总是需要一些外挂配置,云原生应用的实践是在容器化之前就将应用程序配置保留在代码之外。“12-Factors App:Store config in the environment① 外挂配置文件:业务配置 appsettings.json“可以在代码中要求加载appsetting.…

python字符串截取方法_如何使用python语言中的字符串方法截取字符串

在我们使用python语言中的字符串方法时,可能会判断某个字符串是否以什么开头,可以使用什么进行截取等。下面利用几个实例说明字符串中的方法的用法,操作如下:工具/原料 python 截图工具 方法/步骤 1 第一步,打开python…

数据结构——二叉树的层次遍历

问题描述: 给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。 示例: 二叉树:[3,9,20,null,null,15,7] 返回其层次遍历结果: [ [3], [9,…

asp.net core 使用 TestServer 来做集成测试

asp.net core 使用 TestServer 来做集成测试Intro之前我的项目里的集成测试是随机一个端口,每次都真实的启动一个 WebServer,之前也有看到过微软文档上 TestServer 的介绍,当时没仔细看过以为差不多就没用,一直是启动了一个真正的…

微服务很香--麻辣味,但要慢慢消化

前言微服务在编程圈火的是不行不行的啦,可能还有很多小伙伴还没有进行微服务实操,但这个词,要说没听过、没看过,那小伙伴一定是假Programmer。虽然微服务很火,但不能盲目使用;先不说涉及技术和工具有多少&a…

c语言实现灰度图像阈值分割,灰度图像--图像分割 阈值处理之平均阈值

学习DIP第52天转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发:https://github.com/Tony-Tan/DIPpro开篇空话好久没写博客了&…

数据结构——二叉树的双序遍历

设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结 点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树 思路: 1.双序遍历与中序遍历类似,是中序遍历的变形 2.中序遍历是指对于二叉树的每一…

python如何封装成可调用的库_Python实现打包成库供别的模块调用

1.创建python项目bricewulib2.新建test_package包并创建info1类以及print_hello方法3.为了让包的结构再复杂点,我们再在test_package下面新建一个test_package2包并创建Info2类以及print_hello2方法(注意:这里是Info2,不是上面的I…

从零开始实现 ASP.NET Core MVC 的插件式开发(九) - 如何启用预编译视图

标题:从零开始实现 ASP.NET Core MVC 的插件式开发(九) - 升级.NET 5及启用预编译视图作者:Lamond Lu地址:https://www.cnblogs.com/lwqlun/p/13992077.html源代码:https://github.com/lamondlu/Mystique适用版本:.NET…

数据结构——二叉树的层次遍历进阶

之前的一个博客 数据结构——二叉树的层次遍历看完这个,可以简单实现下面的问题 问题: 1.计算二叉树的最大宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值。 2.用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。 解决问题的思路…

future.cancel不能关闭线程_多线程与高并发笔记

1. 创建线程的四种方式实现Runnable 重写run方法继承Thread 重写run方法线程池创建 Executors.newCachedThreadPool()实现Callable接口2. Thread线程操作方法当前线程睡眠指定mills毫秒Thread.sleep([mills])当前线程优雅让出执行权Thread.yield()例如Thread t1, t2&#xff0c…

ANDROID手表怎么设置壁纸,表盘背景随心换 果壳智能手表换壁纸教程

在智能手机和电脑上,我们一般都会换一张自己喜欢的图片作为壁纸,当我们想把一张喜欢的图片做成果壳GEAK Watch表盘时,应该怎么做呢?其实只要简单的几个步骤,你就能获得独一无二的专属表盘。首先,打开一张你…

如何踢掉 sql 语句中的尾巴,我用 C# 苦思了五种办法

一:背景 1. 讲故事这几天都在修复bug真的太忙了,期间也遇到了一个挺有趣bug,和大家分享一下,这是一块sql挺复杂的报表相关业务,不知道哪一位大佬在错综复杂的 嵌套 平行 if判断中sql拼接在某些UI组合下出问题了&#…

数据结构——二叉树的最长路径问题

题目: 求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。 描述 设二叉树中每个结点的元素均为一个字符,按先序遍历的顺序建立二叉链表,编写算法求出该二叉树中第一条最长的路径。 输入 一行数据,为二叉树的先序序…

.NET 应用如何优雅的做功能开关(Feature Flag)

点击上方蓝字关注“汪宇杰博客”导语曾经,我们要在应用程序里做功能开关,就避免不了在配置文件里加上一堆 bool 类型的配置项,然后在代码里用 if else 去判断。尽管这种做法是可行的,但我们现在有办法让代码更加整洁,避…

鼠标右键 移动选定的文件夹到指定位置_iRightMouse:一款免费Mac鼠标右键增强神器...

如果你是多年的Windows用户转到macOS平台,你必定会发现Windows上很多非常方便的鼠标右键菜单在macOS上都是没有的,例如新建txt文档、一键隐藏文件等。而这些快捷功能的缺失也确实会带来一些不便,奇客君发现一款刚刚上线的免费右键增强工具&am…

数据结构——从叶子结点到根节点的全部路径

问题 给定一个二叉树,返回所有从根节点到叶子节点的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-paths 257.二叉树的所有路径 与…