zsy姐姐的NH-03:关于浮点数精度问题的一些研究

其实还没有完全解决这个问题,先写着,发现写不下去就删帖
c语言的作业越来越ex人啦~
本周又做了一道“这位更是重量级”的NH-03

这道题看上去人畜无害,交了一发WA后才发现其ex之处:浮点数的精度问题
请看其测试案例:

x=0.0000       |0.0000
y=0.0000       |0.0000
r=3043.2868    |99824.4353
x0=99778.0351  |24721.0328
y0=99824.4353  |96714.9855
ans=No         |YES

(果然选修题的数据范围开的都离谱。。。)
本题直接用double储存会损失精度而WA,因此我们想探索一下浮点数的精度储存机制(我们是怎么死的
浮点数在内存储存中分为三个部分:符号位,指数位,尾数位
float(单精度浮点数):32bit,分配:1,8,23;
double(双精度浮点数):64bit,分配:1,11,52;
储存时先把浮点数转化为二进制的科学计数法,
小数保存为二进制:把小数不断×2,取整数部分)
eg:20.59375(float)

(20.59375)10=(10100.10011)2
//然后把二进制移位变为科学计数法
(10100.10011)2=1.010010011*2^4 // 左移了4位

转换完成,下一步把它写成符号位+指数位+尾数位叭~
因为float指数位为8bit,可以表示-127~128
(为什么会有负数:如果只有小数部分,那么需要右移小数点. 比如右移3位才能放到第一个1的后面, 就是-3),
然鹅我们并不想要负数,于是我们可以每个数都加上127(double+1023)
所以指数位(阶码)为:127+4=131
最后存储为:0(符号位)100 1001 1(阶码)010 0100 11(尾数)00 0000 0000 0000(后面补零补满36位)=(41A4C000)16
所以我们发现:
二进制科学计数法第一位一定是1
而又因为计算机很懒,肯定会尽可能节省空间,所以储存浮点数尾数时不储存第一位
因此float的精度为23+1=(24)2=(16 777 216)10=1e7
double的精度为52+1=(53)2=(9.007199254741e+15)10 //十六位左右
到这里我们大概学会了浮点数储存和精度
但似乎还解决不了上面的问题
因为我现在还不会捏~

posted @ 2022-03-11 09:30  misasteria  阅读(69)  评论(0编辑  收藏  举报