double的取值范围为什么那么大?

虽然从一开始学编程开始就知道double,float是浮点数,是有精度的,有误差的,但是也就是浅显的认为1.6123271111…的精度对我们来讲只需要到7就结束了,从来没有思考过这个精度具体是指的什么,误差从哪来的?double的取值范围为什么那么大?

先说一下为什么会想到这个问题吧…

今天觉得snprintf/_gcvt不够效率,我想手工做一个double转char*并去除无效0的函数,然后讲double拆为整形部分和小数部分,分别进行转换运算,一开始使用了__int64来表示整数部分,函数编写好了,运行了一下ok,测试了一下,耗时是snprintf的1/4;不错,本来该结束了,但是想了下,能表示DBL_MAX吗?

果断的出错了…

那么,double内存中占8Byte,64bit,__int64也占8Byte,64bit,按理讲__int64标识double的整数部分应该绰绰有余啊,怎么就出错了呢…

那么我们看下
DBL_MAX:1.7976931348623158e+308
INT64_MAX:9223372036854775807

差这么多,不科学啊,找资料:

https://en.wikipedia.org/wiki/Floating-point_arithmetic
http://blog.csdn.net/tercel_zhang/article/details/52537726
https://wenku.baidu.com/view/437c821152d380eb62946d1f.html
http://www.cnblogs.com/fandong90/p/5397260.html
http://www.fmddlmyy.cn/text60.html
http://blog.csdn.net/gjw198276/article/details/6956244

找了很多,这几篇讲的比较透彻,对解决这一问题有帮助

别急,慢慢读,原来double的解释方式和平常见到的整形表示方式并不一样,它在内存中采用了二进制的科学计数法。
IEEE关于浮点数的协定

double包含64个bit
第0位符号位,
第1位至12位标识指数位
第13至64位表示尾数

正因为这样,所以他可以表示远超于±2^63之外的数;但这也带来了精度的问题,它并不能完整的标识范围内的每个具体数值,会有误差的存在;它表示的是一个可接受的范围。
看下边这组数字机器二进制表示:

0.1
0
01111111011
1001100110011001100110011001100110011001100110011010

1.0
二进制:1
0
01111111111
0000000000000000000000000000000000000000000000000000

2.0
二进制:10
0
10000000000
0000000000000000000000000000000000000000000000000000

3.0
二进制:11
0
10000000000
1000000000000000000000000000000000000000000000000000

4.0
二进制:100
0
10000000001
0000000000000000000000000000000000000000000000000000

5.0
二进制:101
0
10000000001
0100000000000000000000000000000000000000000000000000

DBL_MAX:2(2046-1023)*(1+1-2-52)
二进制:1111111111111111111111111111111111111111111111111111
0
11111111110
1111111111111111111111111111111111111111111111111111

有没有发现什么,实际上就是移位,数符,阶符,阶码(阶数),数码(尾数),这个就不再拆开聊了,得写一大章…

这说明了一个问题,也就是把计算机中的double按照我们平常的思维去拆成整数和小数部分,然后在分别用取余的方式来转换为字符串的思路实际上是绕路了,而且如果double值过大还有溢出的错误。

那么怎么转呢,思路应该是按位取出这64个bit,再根据IEEE的浮点数规则去进行转换才是正道。

实际上关于浮点数的部分计算机组成原理上都有讲,只不过当时没有深入思考过…

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值