算法竞赛入门经典(第2版)习题3-12 浮点数 Floating-Point Numbers UVa11809
2014-07-21 09:41
405 查看
这题有点逼近我的智商上限了,看了好几遍才明白大概意思。编程的时候脑子里一直有点乱,卡了我将近一周,代码整体重写了三次。每次都可以实现样例,但是一直WA。
本来都打算跳过去了,但总是有点不甘心。
决定尝试最后一次:把所有可能情况的输入数据都算出来当做测试数据,最终发现WA是由于浮点数转换成整数时的系统误差导致的。
印象里书中样例曾经在浮点数转换整数时+0.5,我这里没有这样做
结果在某个测试样例中double 1.0000000*1000000000转换为整数的结果成了999999999,最终导致WA。
修改了这个bug后,顺利ac。
思路如下:
1.利用10^1=1.25*2^3逐级推算出1<=n<=10时10^n与2^m的换算公式组
2.推算出0<=M<=9各值时所有的十进制小数尾数,得到M表
3.推算出1<=E<=30各值时所有的2的十进制阶数,得到E表
4.读入s串并分割,把输入尾数存在double ap中,阶码存在int B中
5.利用第一步中求出的公式把10^int B转换为中转十进制浮点数double zz*(2^int E)其中1<=zz<2
6.计算出中转十进制浮点数zz* ap 结果存入 double apzz,其中0.5<=apzz<1,并修正E值
7.用apzz在M表中查询,得到M值
8.用E在E表中查询,得到E值
本来都打算跳过去了,但总是有点不甘心。
决定尝试最后一次:把所有可能情况的输入数据都算出来当做测试数据,最终发现WA是由于浮点数转换成整数时的系统误差导致的。
印象里书中样例曾经在浮点数转换整数时+0.5,我这里没有这样做
结果在某个测试样例中double 1.0000000*1000000000转换为整数的结果成了999999999,最终导致WA。
修改了这个bug后,顺利ac。
思路如下:
1.利用10^1=1.25*2^3逐级推算出1<=n<=10时10^n与2^m的换算公式组
2.推算出0<=M<=9各值时所有的十进制小数尾数,得到M表
3.推算出1<=E<=30各值时所有的2的十进制阶数,得到E表
4.读入s串并分割,把输入尾数存在double ap中,阶码存在int B中
5.利用第一步中求出的公式把10^int B转换为中转十进制浮点数double zz*(2^int E)其中1<=zz<2
6.计算出中转十进制浮点数zz* ap 结果存入 double apzz,其中0.5<=apzz<1,并修正E值
7.用apzz在M表中查询,得到M值
8.用E在E表中查询,得到E值
//#define LOCAL //#define TESTING #include<stdio.h> #include<math.h> #include<string.h> #define MAXN 1000 char s[25]; long DM[10]; int main() { #ifdef LOCAL freopen("xt3-12.in","r",stdin); freopen("xt3-12-1.out","w",stdout); #endif //计算10^(10^n)=double zw[]*2^long long zj[]公式组 #ifdef TESTING printf("计算10^(10^n)=double zw[]*2^long long zj[]公式组\n"); #endif long long zj[10]; double zw[10] ; int tempz=1; memset(zj,0,sizeof(zj)); memset(zw,0,sizeof(zw)); zj[0]=3; zw[0]=1.25; for(int i = 1; i<=9; i++) { zj[i] = 10*zj[i-1]; zw[i] = pow(zw[i-1],10); for(int j = 0; j < 10; j++) { if(zw[i]>2) { zw[i]/=2; zj[i]++; } else break; } tempz *= 10; } for(int i = 1; i<=9; i++) { #ifdef TESTING printf("10^(10^%d)=zw[%d]%.15lf*2^zj[%d]%lld\n", i,i,zw[i],i, zj[i]); #endif } //计算结束 //求M表 #ifdef TESTING printf("可能的十进制m值\n"); #endif double m[15]; memset(m,0,sizeof(m)); for(int i = 0; i <= 9; i++) { m[i]=(pow(2,i+1)-1.0)/pow(2,i+1); #ifdef TESTING printf("m[%d]=%.15lf\n", i, m[i]); #endif } //求M表结束 //求e表 long long e[35]; e[0]=0; e[1]=1; for(int i = 2; i<=30 ;i++) { e[i]=e[i-1]+pow(2,i-1); } #ifdef TESTING printf("e表,2^E\n"); for(int i = 0; i<=30;i++) printf("2^E[%d]=2^%ld\n", i, e[i]); #endif //求e表结束 #ifdef TESTING int T = 1; #endif while(scanf("%s",s)!=EOF) { int A,a[15],C,c[15],len; long long E,B=0; double ap = 0,zz; memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); //将s串分割,把尾数存在double ap中,阶码存在int B中 len = strlen(s); if((s[0]=='0')&&(s[1]=='e')&&(s[2]=='0')) break; A = s[0]-'0'; for(int i = 0; i<15; i++) { a[i] = s[16-i]-'0'; ap = (ap+a[i])/10.0; } ap += A; for(int i = 0; i<(len-18); i++) { B *= 10; B += s[i+18]-'0'; } //分割保存结束 //把10^B转换为中转十进制浮点数D:zz*(2^E) #ifdef TESTING printf("\nCase:%d\n把10^B转换为中转十进制浮点数D:zz*(2^E)\n",T++); #endif E = 0; zz = 1.0; int tempB,ij = 0; tempB = B; while(tempB!=0) { E+=zj[ij]*(tempB%10); zz *= pow(zw[ij],tempB%10); while(zz>2) { zz /= 2; E++; } #ifdef TESTING printf("E=%lld zz=%.15lf tempB=%d tempB%10=%d\n", E, zz,tempB,tempB%10); #endif tempB=tempB/10; ij++; } #ifdef TESTING printf("E=%lld zz=%.15lf B=%lld\n", E, zz,B); #endif //转换结束 //计算 中转十进制浮点数D:zz* ap 结果存入 0.double apzz //(intC.int c[ ]*(2^E)=A.a[]*(10^B)) double zz2,apzz; if(zz>0) { apzz = ap * zz; int tempapzz=apzz*10000000+0.5; while(tempapzz>=10000000) { apzz /= 2; tempapzz /=2; E++; #ifdef TESTING printf("tempapzz=%d apzz=%.15lf\n", tempapzz,apzz); printf("\n"); #endif } } #ifdef TESTING printf("apzz:%.15lf E:%lld\n", apzz,E); printf("len=%d s=%s\n", len, s); printf("s=%.15lfe%lld\n", ap,B); printf("\n"); #endif //计算结束 //根据apzz查M表 确认M值 输出 long long tempm,M; tempm = apzz*10000000; for(int i = 0; i < 10; i++) { #ifdef TESTING printf("tempm=%lld m[%d]=%.15lf\n",tempm,i,m[i]); #endif int tempmi = m[i]*10000000; if(tempm == tempmi) { M = i; break; } } printf("%d ", M); //根据apzz查M表 确认M值 输出 结束 //根据E查e表 确认e值 输出 for(int i = 0; i <= 30; i++) { if(E==e[i]) { printf("%d\n",i); break; } } //根据E查e表 确认e值 输出 结束 } return 0; }
相关文章推荐
- 习题3-12 浮点数(Floating-Point Numbers, UVa11809)
- 习题3-12 浮点数(Floating-Point Numbers, UVa11809)
- 算法竞赛入门经典(第2版)第一章习题(Java)
- 算法竞赛入门经典(第2版)习题3-1 得分 Score UVa1585
- 算法竞赛入门经典(第2版)习题3-8 循环小数 Repeating Decimals UVa202
- 算法竞赛入门经典(第2版)习题3-11 换低挡装置 Kickdown UVa1588
- 算法竞赛入门经典(第2版)习题4-1 象棋 Xiangqi UVa1589
- 算法竞赛入门经典(第2版)习题4-5 IP网络 IP Networks UVa1590
- 算法竞赛入门经典(第2版)3.4.9上机练习习题
- 算法竞赛入门经典(第2版)习题3-2 分子量 Molar Mass UVa1586
- 算法竞赛入门经典(第2版)习题4-6 莫尔斯电码 Morse Mismatches UVa 508
- JAVA代码—算法竞赛入门经典(第2版)刘汝佳题解—习题2-1 水仙花数
- 算法竞赛入门经典(第2版)第二章习题(Java)
- 算法竞赛入门经典(第2版)习题3-3 数数字 Digit Counting UVa1225
- JAVA代码—算法竞赛入门经典(第2版)刘汝佳题解—习题2-2 水仙花数
- 算法竞赛入门经典(第2版)习题3-4 周期串 Periodic Strings UVa445
- 习题3-12 浮点数 UVa11809
- 算法竞赛入门经典(第2版)习题2-6
- 算法竞赛入门经典(第2版)习题3-5 谜题 Puzzle UVa227
- 算法竞赛入门经典(第2版)习题3-9 子序列 All in All UVa10340