float的表示

2023-05-16



先说一下计算机中二进制的算法:

  • 整数
    整数的二进制算法大家应该很熟悉,就是不断的除以2取余数,然后将余数倒序排列。比如求9的二进制:

    9/2=4 余 1

    4/2=2 余 0

    2/2=1 余 0

    1/2=0 余 1

    一直计算到商为0为止,然后将得到的余数由下到上排列,就得到了9的二进制:1001。

    从上面的算法我们可以看到,用整数除以2,最终都能够到0。因此,整数是可以用二进制来精确表示的。
  • 小数
    小数的二进制算法和整数的大致相反,就是不断的拿小数部分乘以2取积的整数部分,然后正序排列。比如求0.9的二进制:

    0.9*2=1.8 取 1
    0.8*2=1.6 取 1

    0.6*2=1.2 取 1

    0.2*2=0.4 取 0

    0.4*2=0.8 取 0

    0.8*2=1.6 取 1

    … …

    如此循环下去。因此我么得到的二进制小数也是无限循环的:0.11100110011...

    从小数的二进制算法中我们可以知道,如果想让这种算法停止,只有在小数部分是0.5的时候才可以,但是很不幸,这类的小数很少。所以大部分小数是很难用二进制来精确表示的。

------------------------我是分割线------------------------------

OK,有了上面的知识,我们进入正题:看看float类型在内存中是如何表示的。
 
float类型又称为单精度浮点类型,在
IEEE 754-2008 中是这样定义它的结构的:

  S     EEEEEEEE      FFFFFFFFFFFFFFFFFFFFFFF
31   30        23    22                               0

 

float类型总共4个字节——32位:

  1. 符号位
    其中最左边的为符号位,0为正,1为负。
  2. 指数
    接下来的E是指数,一共8位,也用二进制来表示。
  3. 尾数
    最后的F是小数部分,尾数正是由这23位的小数部分+1位组成的。(这个稍后解释)。

这里我们需要多说一下指数。虽然指数也是用8位二进制来表示的,但是IEEE在定义它的时候做了些手脚,使用了偏移来计算指数。

IEEE规定,在float类型中,用来计算指数的偏移量为127。也就是说,如果你的指数实际是0,那么在内存中存的就是0+127=127的二进制。稍后我们来看这个到底如何使用。

 

好了,看了这么多,我们该演示一下计算机如何将一个十进制的实数转换为二进制的。就拿6.9这个数字来举例吧。-_-||!

 

首先,我们按照上面说的方法,分别将整数和小数转换成对应的二进制。这样6.9的二进制表示就是110.1110011001100...。这里就看出来 了,6.9转换成二进制,小数部分是无限循环的,这在现在的计算机系统上是无法精确表示的。这是计算机在计算浮点数的时候常常不精确的原因之一。

 

其次,将小数点左移(或右移)到第一个有效数字之后。说的通俗些,就是把小数点移到第一个1之后。这样的话,对于上面的110.1110011001100...我们就需要把小数点左移2位,得到1.101110011001100...。

 

接下来的事情就有意思了。首先我们把得到的1.101110011001100..这个数,从小数点后第一位开始,数出23个来,填充到上面float内存 结构的尾数部分(就是那一堆F的地方),我们这里数出来的就是10111001100110011001100。这里又要发生一次不精确了,小数点后超出 23位的部分都将被舍弃,太惨了。

 

不过,这里有一个可能让大家觉得特别坑爹的事情,就是小数点前面的1也不要了。仔细看看上面的内存结构,确实没有地方存放这个1。原因是这样的:IEEE觉 得,既然我们大家都约定把小数点移动到第一个有效数字之后,那也就默认小数点前面一定有且只有一个1,所以把这个1存起来也浪费,干脆就不要了,以后大家 都这么默契的来就好。这也是为什么我上面说尾数是23位+1位的原因。

 

填充完尾数,该填充指数了。这个指数就是刚才我们把小数点移动的位数,左移为正,右移为负,再按照上面所说的偏移量算法,我们填充的指数应该是2+127=129。转换成8位二进制就是10000001。

 

最后,根据这个数的正负来填充符号位。我们这里是正数,所以填0。这样6.9的在内存中的存储结果就出来了:

0  10000001  10111001100110011001100

 

总结一下,实数转二进制float类型的方法:

A. 分别将实数的整数和小数转换为二进制
B. 左移或者右移小数点到第一个有效数字之后
C. 从小数点后第一位开始数出23位填充到尾数部分

D. 把小数点移动的位数,左移为正,右移为负,加上偏移量127,将所得的和转换为二进制填充到指数部分
E. 根据实数的正负来填充符号位,0为正,1为负

如果需要把float的二进制转换回十进制的实数,只要将上面的步骤倒着来一边就行了。

 

------------------------我是分割线------------------------------

需要注意的东西:

  1. 23位尾数填充的问题
    虽然在IEEE754标准中我没有找到相应的描述,但是在实际处理的时候,截取23位尾数需要对第24位进行零舍一入的操作,至少在Java虚拟机中是这么做的。有兴趣的可以试试0.7f-0.6f。
  2. 运算时向右对阶操作的舍入问题
    这个也是在实际操作时遇到的问题。到目前为止我还无法确定向右对阶操作是否也进行了零舍一入的操作。有兴趣的可以试试9.6f-6.9f。
  3. 指数全零问题
    全部为零的指数说明当前所表示的是一个特殊的float数字。全零的float类型分为两种情况:  
    • 尾数全零。此时代表当前float数为0。根据符号位,分为+0和-0。这两个在JVM上相等的。
      这里需要解释一下。因为IEEE的默认1的问题,所以float类型没有办法表示0,因此只能在已有的规定上做一些强制性的规则来表示0,也就有了上面的这个全零的说法。
       
    • 尾数不全为零。此时说明当前的float数是一个非规格化的数。
  4. 指数全一问题
  5. 指数全部为一也说明这个float数是一个不寻常的数字。它也分为两种情况:  
    • 尾数全零。此时根据符号位的不同,分为正无穷(+infinity)和负无穷(-infinity)。注意,这两个东西在JVM中是不相等的。
    • 尾数不全为零。此时表示此float数纯粹不是一个数(NaN,Not a Number)。这个NaN也分为QNaN(Quiet NaN)和SNaN(Signalling NaN)。至于这两个NaN有什么区别,下面这段话倒是说明了,但是我没有这方面的知识,所以不敢妄加翻译,只好把原文放在这里:
      A QNaN is a NaN with the most significant fraction bit set. QNaN's propagate freely through most arithmetic operations. These values pop out of an operation when the result is not mathematically defined.
      An SNaN is a NaN with the most significant fraction bit clear. It is used to signal an exception when used in operations. SNaN's can be handy to assign to uninitialized variables to trap premature usage.

      Semantically, QNaN's denote indeterminate operations, while SNaN's denote invalid operations.

      最后一句话说的明白,QNaN就是一个不确定操作的结果,而SNaN纯粹就是一个非法的操作结果。

------------------------我是分割线-----------------------------

OK,废话了这么多,我觉得对float类型也大致有个了解了。float明白了以后,double类型也就好说了,基本和上面一样,只是指数和尾数的位数不一样而已。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

float的表示 的相关文章

  • java中float怎么写_java中float是什么意思

    Java中float的意思 浮动 xff0c 代表的是一种浮点数数据类型 xff0c 它内存分配4个字节 xff0c 占32位 范围从 10 38 到 10 38 和 10 38 到 10 38 float型定义的数据末尾必须有 f 或 F
  • string与float数据的转换

    问题 xff1a 如何将6位小数的string数据转化为2位小数的float数据显示 xff1f 先通过atof 转化为6位小数的float数据 xff1b temp 61 atof strtemp sscanf 61 strtemp 34
  • 强大的PropertyGrid

    PropertyGrid 做工具一定要用这东西 把要编辑的对象看成类的话 所有要编辑的属性就是成员 嗯嗯 最近看了几眼Ogitor 它对于PropertyGrid的使用就很不错 所有要编辑的对象 灯光 模型 粒子等等 都有一个共同的基类 每
  • ThreeJS中的相机

    在ThreeJS中一共有三个关于相机的JS文件 Camera js OrthographicCamera js PerspectiveCamera js 分别是普通的相机 正交 正投影的相机 第三人称相机 首先是普通的相机 Camera j
  • 编码-小数

    C语言中对于小数 采用float 单精度浮点型 和double 双精度浮点型 来存储 Float 不管是float还是double 在存储中都分为三部分 第一位s代表符号位 1代表负数 0代表正数 第二个域是指数域e 对于单精度float类
  • VC编译的五子棋游戏核心算法分析(附源码)

    转载请标明是引用于 http blog csdn net chenyujing1234 前段时间在CSDN的资源里载得五子棋VC的源码 由于忘了链接地址 这里没有标明出处 请作者谅解 但我也把在VS2005上编译通过且加入清楚的注释的源码放
  • Unity3D脚本中文系列教程(四)

    二 运行时类 AnimationCurve 类 动画曲线 在给定的时间添加关键帧并确定曲线 变量 var keys Keyframe 描述 定义在动画曲线中的所有键 这让你从数组中清理 添加或移除键 如果键没有按照时间顺序 它们会在赋值的时
  • GLSL学习笔记

    From http apps hi baidu com share detail 19177385 GLSL语言内置的变量 包括内置的顶点属性 attribute 一致变量 uniform 易变变量 varying 以及常量 const 一
  • VC++ 教程

    基本概念 对象 面向对象编程2 定义实体后 可以不知道此实体的功能是怎样实现的 也能使用它们 核心概念 1 数据封装 将一个数据与这个数据有关的操作集合封装在一起 形成一个能动的实体 称为对象 2 继承 在面向对象语言中 类功能支持层次机制
  • 整理 firefox 和IE系列的相关差别,已备后用!

    一 IE与FireFox的js和css png透明 AlphaImageLoaderfilter progid DXImageTransform Microsoft AlphaImageLoader enabled bEnabled siz
  • 函数覆盖与函数隐藏

    derive cpp 定义控制台应用程序的入口点 include stdafx h include
  • 文字模糊效果(Opencv实现)

    效果图 实现过程 该方法以photoshop中的图层为基本思想 对文字的处理 实际上是将图片作为一幅图像来处理的 而背景是一幅图像 即另一个图层 1 读取文字图片 将图片进行高斯模糊 因高斯模糊是一个卷积的过程 所以可以设定卷积因子的大小
  • C/C++基本数据类型所占字节数

    关于这个基本的问题 很早以前就很清楚了 C标准中并没有具体给出规定那个基本类型应该是多少字节数 而且这个也与机器 OS 编译器有关 比如同样是在32bits的操作系统系 VC 的编译器下int类型为占4个字节 而tuborC下则是2个字节
  • 浮点数在计算机中存储方式

    C语言和C 语言中 对于浮点类型的数据采用单精度类型 float 和双精度类型 double 来存储 float数据占用32bit double数据占用64bit 我们在声明一个变量float f 2 25f的时候 是如何分配内存的呢 如果
  • Geometry Shader 概念和实例

    前言 Shader Model 4给我们带来了Geometry Shader这个玩意儿 其实这个东西早就在一些3D动画制作软件中存在了 比如Maya 8 我参考了以前DX10的哪一篇Preview与Csustan edu的一篇比较详尽的教材
  • javascript中的float运算精度

    有人问到一个js问题 var i 0 07 var r i 100 alert r 结果为什么是7 0000000000000001 查了下资料 其实我们知道JavsScript中 变量在存储时并不区分number和float类型 而是统一
  • CJson-修改浮点数的位数

    现状 调用cJSON Print 将组成的json转为字符串格式时 对于浮点数的位数是不固定的 length sprintf char number buffer 1 15g d 源代码里用的是 1 15g 代表输出字符最少一位 最大15位
  • VC++实现视频压缩编码标准 MPEG-4

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家提出意见 一起讨论 需要源码的请与我联系 参考书籍 lt
  • 在GPU上实现光线跟踪

    include cuda h include book h include cpu bitmap h define DIM 1024 生成图像的大小 DIM DIM define SPHERES 20 生成的图像中球体的个数 define
  • Qt数据类型与强制转换(转)

    类型转换 把QString转换为 double类型 方法1 QString str 123 45 double val str toDouble val 123 45 方法2 很适合科学计数法形式转换 bool ok double d d

随机推荐

  • 无法定位程序输入点 _ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEC1Ev于动态链接库

    在执行编译出来的exe时 xff0c 报了 无法定位程序输入点 ZNSt7 cxx1118basic stringstreamIcSt11char traitsIcESaIcEEC1Ev于动态链接库 的异常 出现这个问题时 xff0c 应该
  • 踩了个C++的未定义标识符"cout"的坑

    问题表现 没怎么用过C 43 43 写过完整的项目 xff0c 今天闲来无事 xff0c 便创建个c 43 43 的工程玩玩 xff0c 结果一个简单的打印输出就给卡住了 xff0c 无法打开文件 iostream h xff0c cout
  • Electron-Vue之安装流程

    近期摒弃了熟悉的WPF xff0c 选用了新的一套工具 xff08 Electron Vue xff09 来开发桌面软件 xff08 我是连html都没用过的猿 xff0c no zuo no die xff09 接触新的东西 xff0c
  • vscode的调试配置

    文章目录 vscode的调试配置文件调试配置选项 vscode的调试配置文件 vscode的调试配置存储在 vscode文件夹的launch json文件中 通过以下步骤可以创建一个调试配置 xff1a 切换到调试视图单击create a
  • C/C++实现strcpy和strcat两个功能

    strcpy和strcat是string h头文件中分别实现字符串数组拷贝与拼接功能的函数 xff0c 详细使用相信大家都了解了 xff0c 如果还不了解看看实例 C C 43 43 笔试必须熟悉掌握的头文件系列 xff08 四 xff09
  • C/C++锁机制(boost)的认知和使用

    锁扩充 加锁的必需考虑三个问题 该锁的不锁 xff0c 将会导致各种莫名其妙的错误 xff1b 加锁范围太大 xff0c 虽然能避免逻辑错误 xff0c 但如果锁了不该锁的东西 xff0c 难免会降低程序的效率 xff1b 加锁方式不合适
  • QT之GPS

    http blog sina com cn s blog 7da13b510100xtgr html 前几天发现手里还闲着一块GPS 佳明的15W 也不知道是好的还是坏的呵呵一时兴起我就趁周六日没什么事情 用qt做了一个界面 现在已经调试完
  • 关于tcp/udp网络调试助手错误提示

    最近在学习网络调试助手与虚拟机中的Ubuntu系统通信 xff0c 在使用Ubuntu做服务器端时 xff0c tcp以及udp协议都遇到了问题 1 tcp协议遇到的问题是 xff1a 网络调试助手提示 xff1a 1035未知错误 xff
  • 结构体和结构体链表

    在c语言表针中有多种数据类型 xff0c 他们的应用使变量的应用变得灵活多变 而除了c语言默认的int xff0c float 等类型外 xff0c 我们还可以自己定义一些数据的类型 xff0c 结构体类型便是可以实现数据类型自定义的类型
  • 串口通信UART

    串口基本概念 串口通讯 Serial Communication 是指外设和计算机间 xff0c 通过数据信号线 地线等 xff0c 按位进行传输数据的一种通讯方式 其通讯协议可分层为协议层和物理层 物理层规定通信协议中具有机械 电子功能的
  • 一、Fmcw毫米波雷达原理

    0 概念 FMCW Frequency Modulated Continuous Wave xff0c 即调频连续波 FMCW技术和脉冲雷达技术是两种在高精度雷达测距中使用的技术 其基本原理为发射波为高频连续波 xff0c 其频率随时间按照
  • Makefile和CMake

    Makefile makefile主要规则 xff1a 伪对象 PHONY clean 规则1 main main o gcc main o o main 规则2 main o main c gcc c main c o main o 规则
  • C语言基础——结构体

    结构体的作用 在需要表示一些复杂信息时 xff0c 使用单纯的数据类型很不方便 比如 xff1a 学生信息 xff08 学号 xff0c 姓名 xff0c 班级 xff0c 电话 xff0c 年龄 xff09 xff1b GPIO信息 xf
  • Nginx 通过 header 中的标识进行分发

    Nginx可以根据请求头中自定义的标识将请求分发到不同的服务器 具体来说 xff0c 可以使用map指令将请求头中的自定义标识映射为不同的后端服务器地址 xff0c 然后使用proxy pass指令将请求转发到对应的后端服务器 以下是一个示
  • DB9接口详解---DB9引脚在 UART,CAN,RS485中的定义

    DB9的公母如下 xff1a 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • 超强整理!PCB设计之电流与线宽的关系

    关于pcb线宽和电流的经验公式 xff0c 关系表和软件网上都很多 xff0c 本文把网上的整理了一下 xff0c 旨在给广大工程师在设计PCB板的时候提供方便 以下总结了八种电流与线宽的关系公式 xff0c 表和计算公式 xff0c 虽然
  • nginx 主动健康检查搭建详解(nginx_upstream_check_module)

    版本信息 nginx 1 21 1 下载nginx upstream check module模块 nginx upstream check module master zip wget https codeload github com
  • paddle推理部署(cpu)

    我没按照官方文档去做 xff0c 吐槽一下 xff0c 官方文档有点混乱 一 概述 总结起来 xff0c 就是用c 43 43 示例代码 xff0c 用一个模型做推理 二 示例代码下载 https www paddlepaddle org
  • Vector的用法

    我不知道大家是怎么理解Vector和怎样使用的 xff0c 这篇文章主要是发表我自己对于Vector的看法 xff0c 仅仅属于个人理解 xff0c 如果有什么错误 xff0c 也希望大家指正哈 目录 1 xff1a Vector的概念 2
  • float的表示

    xfeff xfeff 先说一下计算机中二进制的算法 xff1a 整数 整数的二进制算法大家应该很熟悉 xff0c 就是不断的除以2取余数 xff0c 然后将余数倒序排列 比如求9的二进制 xff1a 9 2 61 4 余 1 4 2 61