本文主要记录一下Float的一些基础知识。

在计算机界,有个规定叫IEEE754,它规定了如何以二进制的方式来存储10进制的数。

按照这个规定,单精度浮点数(float)这个数据类型所占内存大小为4个字节,也就是32位,所以单精度浮点数也叫32位浮点数,它在内存或硬盘中要占用32个比特。

字节就是存储数据的单位,并且是硬件所能访问的最小单位
1字节 = 8位
1K = 1024字节

二进制和十进制的互相转换

十进制与二进制的相互转换流程:
二进制转十进制:按权相加法。
十进制转二进制:除2取余,逆序排列。

二进制到十进制:
例一:10010 = 0 * 20 + 1 * 21 + 0 * 22 + 0 * 23 + 1 * 24 = 18 ;
例二:1010.11 = 1 * 23 + 0 * 22 + 1 * 21 + 0 * 20 + 1 * 2-1 = 10.5;
例三:1010.11 = 1 * 23 + 0 * 22 + 1 * 21 + 0 * 20 + 1 * 2-1 + 1 * 2-2 = 10.75
在小数点后的第n位,则乘以2-n

十进制到二进制:
18 / 2 = 9 … 0 ;
9 / 2 = 4 … 1 ;
4 / 2 = 2 … 0 ;
2 / 2 = 1 … 0 ;
1 / 2 = 0 … 1;
然后从下往上取余数,可得10010

以上的十进制数都是不带小数的,下面看看带小数的十进制数是如何与二进制互相转换的:

二进制转十进制:权相加法。
十进制转二进制:整数部分除2取余,逆序排列;小数部分使用乘 2 取整数位,顺序排列,直至小数点后为0;

二进制转十进制:
10.01 = 1 * 2-2 + 0 * 2-1 + 0 * 20 + 1 * 21 = 2.25

十进制转二进制:
整数部分:
2 / 2 = 1 … 0
1 / 2 = 0 … 1
小数部分:
0.25 * 2 = 0.5 … 0
0.5 * 2 = 1 … 1
整数部分从下往上取结果,是10。小数部分是从上往下取结果,是01,即10.01

二进制存储十进制的规范

举例说明,有个十进制的数10.75,它的二进制数是1010.11,再规范化后就是1.01011 * 23

规范化就是指把二进制数转化成“尾数 * 2指数”的形式,即把尾数的小数点放在第一位和第二位之间,然后保证第一位非0,再将尾数乘以2n。 上面的“1.01011”就是尾数,

Float的存储结构

一个浮点数(Floating Point Number)由三个基本成分构成:

  • 符号位(Sign)(占1位)

  • 偏移指数位(阶码、指数)(Exponent)(占8位)

    偏移指数位用来表示“规范化”后的指数值,上面以十进制数10.75为例,它的二进制数规范化后是1.01011 * 23,这里的“3”就是指数值。

    为什么叫偏移呢,就是因为根据那个IEEE754规定,在单精度浮点数中,指数值的范围是-127~128。为了表示起来更加方便,浮点数的指数位都有一个固定的偏移量,偏移后的指数等于实际的指数加上偏移量,从而保证“偏移后的指数”总是一个非负整数,这样,指数位部分就不用为如何表示负数而担心了。

    IEEE754规定了float浮点数的指数的偏移量是127。这里同样以上述的十进制数10.75为例:
    二进制数规范化后是:1.01011 * 23
    指数值是:3
    则偏移指数值就是:3 + 127 = 130(加上127这个偏移量,避免出现负数)

    偏移指数位(130的二进制表示):1000 0010(8位比特的二进制)

    摘录自:什么是浮点数?10分钟彻底掌握浮点数的底层原理 #安员外读书会

  • 尾数位(Mantissa)(占23位)

    就是小数点后面的那些小数

对于 32 位的单精度浮点型如下:

有 1位符号位(S),8位偏移指数位(P),23位尾数(M)

例:

十进制数16.5,转换为二进制数是:10000.1,规范化后是:1.00001 * 24
符号位(S):这个数是正数,所以为0
偏移指数位(P):看规范化后的式子,指数是4,所以就是偏移指数就是4+127=131。131的二进制形式是1000 0011,这就是8位的便宜指数位。
尾数(M):看规范化后的式子,小数部分是00001,这个就是尾数位了,但由于这个尾数部分总共有23位,所以还要在后面补18个0,所以完整的尾数部分是:0000 1000 0000 0000 0000 000

所以10进制的数字16.5在内存的表示为:

符号位(S) 指数部分(P)(8位) 尾数部分(M)(23位)
0 1000 0011 0000 1000 0000 0000 0000 000

(参考来源https://blog.csdn.net/qq_34719188/article/details/83351918)

精度问题

float只能得到7位(包括整数部分和小数部分)精确数:

#include <stdio.h>
int main()
{double a = 1.0;float b = 2.3;printf("a = %f \n",a/3);printf("b = %f \n",b);return0;
}
运行结果:a = 0.333333b = 2.300000

在C语言中,用%f输出单精度浮点数只有7位有效数字(整数部分和小数部分一共7位)
单精度浮点数的尾数部分用23位存储,加上默认的小数点前的1位1,2(23+1) = 16777216。
因为 107 < 16777216 < 108,所以说单精度浮点数的有效位数是7位
(摘自为何float有效位数为7位?)

float的小数可能会不精准:

#include <stdio.h>
int main()
{float a = 1.1;float b = 12.12;float c = 123.123;float d = 1234.1234;float e = 12345.12345;float f = 123456.123456;printf("a = %f \n",a);printf("b = %f \n",b);printf("c = %f \n",c);printf("d = %f \n",d);printf("e = %f \n",e);printf("f = %f \n",f);return 0;
}

运行结果为:

a = 1.100000
b = 12.120000
c = 123.123001
d = 1234.123413
e = 12345.123047
f = 123456.125000

为什么精度会有问题:

根据上面十进制与二进制互相转换的方法,以十进制数2.1为例
转成二进制:
整数部分:
2 / 2 = 1 … 0
1 / 2 = 0 … 1
小数部分:
0.1 * 2 = 0.2 … 0
0.2 * 2 = 0.4 … 0
0.4 * 2 = 0.8 … 0
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.6 * 2 = 1.2 … 1
0.2 * 2 = 0.4 … 0
0.4 * 2 = 0.8 … 0
0.8 * 2 = 1.6 … 1
0.6 * 2 = 1.2 … 1

结果会发现十进制的0.1在二进制中并不能精确表示,只能用无限的小数位来逼近0.1。而计算机在存储小数时是有长度限制的(毕竟存储空间有限),所以会进行截取部分小数进行存储,从而导致计算机存储 2.1 这个十进制数字的值只能是个大概的值,而不是精确的值。

= 1.6 … 1
0.6 * 2 = 1.2 … 1

结果会发现十进制的0.1在二进制中并不能精确表示,只能用无限的小数位来逼近0.1。而计算机在存储小数时是有长度限制的(毕竟存储空间有限),所以会进行截取部分小数进行存储,从而导致计算机存储 2.1 这个十进制数字的值只能是个大概的值,而不是精确的值。

(参考来源:详谈浮点精度(float、double)运算不精确的原因)

补充

有一个浮点型变量,如何判断x的值是否为零

if(0 == x)x是0
elsex不是0

上面这个判断方式对于浮点数来说是错误的,因为在float数据类型中,小数是以近似值来存储的

这里我有些不懂:

在一些教学视频中,说判断浮点数x是否为0应该这样写:

if(|x-0.000001| < 0.000001)x是0
elsex不是0

再上网查,发现这样写的都是直接照搬,没说为啥,或者说了我也看不太懂的。

为什么是看x与0.000001的距离而不是看x与0.000000的距离,|x-0.000001| < 0.000001在数学上不是等价于0<x<0.000002吗

为什么不是

if(|x-0.000000| <= 0.000001)x是0
elsex不是0

参考网上看到对我来说能看得懂,也能接受的是这样的:

参考了有一个浮点型变量 X,如何判断它是否为 0 ?用除法可以吗?中用户Uron的评论
再结合Comparison of a float with a value in C中,最后那里的Example no 2

if(fabs(x) < 0.0000001)x是0
elsex不是0

fabs()函数是用来求绝对值的,它在math.h这个头文件里面定义。

C语言中的float(单精度浮点数)相关推荐

  1. c语言程序float的意思,c语言中的float表示什么意思?

    c语言中的float表示什么意思? 发布时间:2020-04-03 14:51:43 来源:亿速云 阅读:384 作者:小新 c语言中的float表示什么意思?很多人都不太了解,今天小编为了让大家更加 ...

  2. double取两位小数_Java语言中:float、double数据类型在内存中是如何存储的

    java语言中,float类型数字在计算机中用4个字节(32位)来存储.double类型占用8个字节(64位). 从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float ...

  3. C语言中double\float类型默认输出几位小数

    首先,吐槽一下,就这么几句话的事情,你就收费,真的不想说啥了~ 然后正文给大家分享一下小数点默认输出的位数 C语言中常用的小数有俩种类型: float  比特数32  有效数字 6~7 double  ...

  4. go语言中的float类型

    package mainimport ("fmt""math" )func main(){// 声明浮点类型变量// 以下三种声明方式均是等价的days := ...

  5. c语言中对float保留固定3位,float保留三位小数 float,double 除法 保留 指定位

    java里怎样让float保留3位小数 数据库里保存的float值是0.0346562 保留小数位3位 如0.035后面的四舍五有一个方法很简单,保留三个小数,就是乘以1000(10的3次方),取整, ...

  6. c语言如何找小数点后有几位皇帝,C语言中,float类型怎么储存小数点后六位的,第六位会四舍五入么?...

    你上面的2个结果写颠倒了吧? -- 这里面涉及到两个精度问题,即printf的指定精度,以及c的数据类似float和double的精度.1printf("%f\n",x); %f, ...

  7. c语言中的float类型,C语言中float类型详解

    C/C++中, 浮点数,float以及 double 在内存中是怎样存储的? 假如,我有32-bit 8bit 8bit 8bit 0 0 0 0 0 1 1 1 1 对于整形int,我们可以很快得出 ...

  8. c语言double类型是几字节,c语言中int long float double 等类型所占字节及输出表示(转)...

    16位编译器 char :1个字节 char*(即指针变量): 2个字节 short int : 2个字节 int: 2个字节 unsigned int : 2个字节 float: 4个字节 doub ...

  9. 什么是java双精度浮点数_什么是浮点型?单精度浮点数(float)和双精度浮点数(double)介绍...

    作为一名java学习者,怎能不懂这些java基础中的基础呢?本文就带各位温顾温顾java浮点型.单精度浮点数.双精度浮点数. 浮点型首先明确java中浮点型数据类型主要有:单精度float.双精度do ...

最新文章

  1. python库文档的错误_自己编程中遇到的Python错误和解决方法汇总整理
  2. Zuul简介及代码示例
  3. ubuntu 13.04 telnet 详细配置
  4. 函数传参之商品价格计算—JS学习笔记2015-6-6(第50天)
  5. ThreadLocal不仅要应付面试,更要真的理解,真的会用
  6. linux导入lifd文件乱码,wget文件名中文乱码
  7. linux 重庆mysql_Linux服务器上MYSQL的安装
  8. 图片转化word文档 在线免费转换
  9. VirtualBox下配置 Ubantu18.4 总纲领
  10. 教你用三种方式打造一款简单的网络播放器
  11. 表达式运算(包含大整数加减乘)
  12. 计算机毕业设计ssm社区爱心活动网站be83l系统+程序+源码+lw+远程部署
  13. 【F28003x】 Enhanced Pulse Width Modulator (ePWM)
  14. Python爬取安居客新房信息
  15. 2019杭电多校第七场 Kejin Player HDU - 6656 (期望)
  16. Python【Feature】高级特性
  17. JAVA内存管理机制
  18. 《乞力马扎罗山的雪》——海明威
  19. 算法学习-回溯法(2)0/1背包问题求解
  20. 直通模式+Traffic Filter

热门文章

  1. 【新书推荐】卡神之路,不过如此
  2. 内连接、外连接、全连接图示语法
  3. Spring boot +Mybaits
  4. 电梯控制算法(5)单电梯场景——屏蔽较近楼层进梯请求
  5. 短信验证码实现(京东万象第三方接口)
  6. VisualStudio2017各版本激活码密钥
  7. vue读取json文件
  8. 【数据处理】格式化数据
  9. post 与get 区别,为什么现在的HTTP通信中大多数请求还是使用get?
  10. 超全!嵌入式系统词汇速查表