【待完善】浮点数

目录

1.十进制小数转换二进制问题

2.浮点数在计算机中的存储方式

3.十进制小数0.1无法被二进制小数准确表示

4.C语言中浮点数的范围和精度

5.浮点数的比较

6.浮点数计算中存在的误差


1.十进制小数转换二进制问题

22.8125转二进制

整数和小数分别转换。

整数除以2,商继续除以2,得到0为止,将余数逆序排列。

22 / 2 11 余0

11/2 5 余 1

5 /2 2 余 1

2 /2 1 余 0

1 /2 0 余 1

所以22的二进制是10110

小数乘以2,取整,小数部分继续乘以2,取整,得到小数部分0为止,将整数顺序排列。

0.8125x2=1.625 取整1,小数部分是0.625

0.625x2=1.25 取整1,小数部分是0.25

0.25x2=0.5 取整0,小数部分是0.5

0.5x2=1.0 取整1,小数部分是0,结束

所以0.8125的二进制是0.1101

十进制22.8125等于二进制10110.1101

 

2.浮点数在计算机中的存储方式

科学技数法的形式,即用一个尾数(Mantissa ),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。比如 123.456 用十进制科学计数法可以表达为 1.23456 × 10^2 ,其中 1.23456 为尾数,10 为基数,2 为指数。

采用IEEE标准

假设是float类型的4字节(32bit)的单精度小数,在内存中是分三部分存储的:

符号位S(1位):0代表正数,1代表负数

指数位E(8位):用于存储科学计数法中的指数数据

尾数部分M(23位):采用位移存储尾数部分

 

8.25   用二进制表示为:1000.01

而用二进制的科学计数法表示 1000.1,可以表示为1.00001 * 2^3

二进制中任何一个数的科学计数法表示都为1. xxx * 2^n,尾数部分就可以表示为xxxx,由于第一位都是1嘛,干嘛还要表示呀?所以将小数点前面的1省略。

指数位E=指数+127

而对于指数部分,因为指数可正可负(占1位),所以8位的指数位能表示的指数范围就只能用7位,范围是:-127至128。所以指数部分的存储采用移位存储,存储的数据为元数据 +127。

注意:

元数据+127:大概是指“指数”从00000000开始(表示-127)至11111111(表示+128)

所以,10000000表示指数1 (127 + 1 = 128 --> 10000000 ) ;

指数为 3,则为 127 + 3 = 130,表示为 01111111 + 11 = 10000010 ;

 

 

按照上述规则

符号位为:0,正

指数位为:3+127=130,10000010;

尾数部分为:00001(缺位的补0)

所以8.25存储方式为0 10000010 00001000000000000000000

 

0 10000010 00001000000000000000000的反推过程 :

10000010(二进制) ==> 130

1.00001*2^(130-127=3)=1000.01,转换成十进制为8.25

 

几个特殊的情形:

指数E全为0时,

指数E全为1时,这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

如果有效数字M不全为0,表示这个数不是一个数(NaN)

参考:http://www.cnblogs.com/wuyuan2011woaini/p/4105765.html浮点数在计算机中的存储方式

http://blog.csdn.net/jjj19891128/article/details/22945441小数在计算机中的存储形式

 

3.十进制小数0.1无法被二进制小数准确表示

来源知乎 慕容小匹夫 陈嘉栋https://www.zhihu.com/question/32304267

我们先来看一看一个十进制的小数0.1为何不能被二进制浮点数准确的表示出来吧。

如同在十进制中,1/3是无法被准确表示的,如果我们要将1/3转换成十进制小数的形式则是:

1/3 = 0.3333333....(3循环)

同理,十进制小数0.1也是无法被二进制小数准确表示,如果我们要将十进制的0.1转换为二进制小数则是:

0.1 = 0.00011001100....(1100循环)

我们可以看到,如果要将十进制的0.1转换为二进制小数,则会出现1100循环的状况。因此根据我在上一篇文章中提到过的IEEE 754标准以及在上一篇文章中最后所举的一个例子,我们首先将0.00011001100....进行逻辑移位,使之小数点左边第一位是1。那么结果是 1.10011001100...,共移动了4位,因此指数相应的应该是-4。所以,表示十进制0.1的float二进制浮点数的结果如下:

符号位:0(表示正数)

指数部分:01111011(01111011换算成十进制是123,因为要减去-127故结果为-4)

尾数部分:10011001100110011001101(即通过移位之后,舍掉小数点左侧的1,留下的小数部分,保留23位)

那么这个用来“表示”十进制小数0.1的float二进制浮点数如果换算成十进制数到底是多少呢?它和0.1到底有多大的误差呢?下面我们就来换算一下:

指数部分:2^(-4) = 1/16

尾数部分:1 + 1/2 + 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + 1/131072 + 1/1048576 + 1/2097152 + 1/8388608 = 1.60000002384185791015625 (在换算成float时会把小数点左侧的1省略,这里需要再次加回来)

那么,换算之后实际的十进制数便是:1.60000002384185791015625 * 1/16 = 0.100000001490116119384765625

所以我们可以看到,二进制浮点数并不能准确的表示0.1这个十进制小数,它使用了0.100000001490116119384765625来代替0.1。

这便是直接使用二进制来表示小数的方式,很有可能会产生误差。

 

4.C语言中浮点数的范围和精度

指数全为1, 若尾数全为0,表示正负无穷大

若尾数不全为0,表示 NaN not a number

指数全为0,若尾数全为0,表示0

若尾数不全为0,表示是非规格化的值,接近0的值

最大值,+,尾数23位全为1,指数位全是1,为255

1.11111111111111111111111*2^(255-127=128)

 

对于单精度浮点数(float)来说,符号位一位,指数位8位,尾数23位。指数能够表示的指数范围为-128~127。尾数为23位。

其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;

以float为例,如下表

符号

尾数

指数

1

23

8

数符(+-)

小数部分(决定精度)

-127~128 指数(决定范围)

例如:

+1.1111111111111111111111*2^127(小数点后面23个1,由于尾数的范围1~2,其最高位总为1,故只需存取小数部分,所以小数为是23位1),约等于2*2^127=3.4*10^38。为3.4*10^38负数亦然。

参考:http://blog.sina.com.cn/s/blog_6ebd49350101gdgo.htmlC语言中关于float、double、long double精度及数值范围理解

 

5.浮点数的比较

C语言用"=="来比较两个浮点数,返回值完全是不确定的。 

因此只能定义一个精度来确定是否相等

#define EPSILON 0.000001//根据精度需要
if(fabs(a-b) < EPSILON)
{
  //a b 近似相等
}

参考:https://blog.csdn.net/jk110333/article/details/8902707 比较两个浮点数是否相等的方法

            https://blog.csdn.net/slience_646898/article/details/80954464 浮点数比较问题

 

6.浮点数计算中存在的误差

 

 

相关文章:

http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html原码, 反码, 补码 详解

http://www.cnblogs.com/kevinq/p/4480563.html定点数与浮点数

https://www.zhihu.com/question/21711083IEEE 754格式是什么?

http://justjavac.com/codepuzzle/2012/11/02/codepuzzle-float-from-surprised-to-ponder.html

http://justjavac.com/codepuzzle/2012/11/11/codepuzzle-float-who-stole-your-accuracy.html代码之谜(五)- 浮点数(谁偷了你的精度?)

 

 

知乎 https://www.zhihu.com/question/32304267

http://www.cnblogs.com/fczjuever/archive/2013/04/16/3023868.html

http://bbs.chinaunix.net/thread-3746530-1-1.html

http://blog.csdn.net/dreamer2020/article/details/24158303

https://books.google.com.hk/books?id=Ni1bnbQRttYC&pg=PT65&lpg=PT65&dq=float%E8%8C%83%E5%9B%B4%E5%92%8C%E7%B2%BE%E5%BA%A6&source=bl&ots=3CroO9Ri4n&sig=SK1-J7ne-3inpi60IzbQvXWPXLE&hl=zh-CN&sa=X&ved=0ahUKEwitlaj3grbWAhXLppQKHe_QAmw4HhDoAQg3MAM#v=onepage&q&f=false

 

 

http://blog.163.com/qimo601@126/blog/static/1582209320135101823454/

http://blog.csdn.net/cppptr/article/details/573372

http://blog.csdn.net/hyforthy/article/details/19649969

http://blog.csdn.net/u010296036/article/details/70766904

 

 

http://blog.csdn.net/lin200753/article/details/27952897 C中double到int的转换、四舍五入

http://blog.sina.com.cn/s/blog_63d1de3d0100gmcz.html C++中的数据类型转换(使用sstream头文件)

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值