习题3-12 浮点数 UVa11809

感悟!

0、本题有一个勘误(并且恰好包含15位有效数字),更正为 小数点后恰好有15位数字,附上原文(英文)

and will have exactly 15 digits after the decimal point.


1、学习double越界处理,采用log10降级处理。

2、认识到计算机处理double、float数据存在误差,(失之毫厘,谬以千里)。

double,float对于逻辑运算符==基本无用。两数是否相等,应采用如fabs(a-b)<1e-6的方式。

int数据的逻辑处理十分简便,故逻辑运算时,我们大量看到的是int数据的处理。

3、第一次看到了,有限结果的建表查询方式。

4、学习了,字符串转数字的读取技巧。

5、编写程序,不能等到全部写完,再来排错,应该写一小段,printf跟踪一段,能极大提高编码成功率与效率。

6、阅读他人代码,有一些心得,解决同一个问题,行数较少的代码比行数较多的代码更容易读懂。

展示给读者的代码越短越好(在容易理解的基础上),建议删除其中的测试代码,增加其中的注释代码。

7、编码尽可能的会写注释了,保证遗忘后,又能很快的把程序拾起。

8、编码水平又提高了一步。


以下是编码,参考了许多作者,在此一并感谢。

环境Dev-cpp4.9.9.2


#include <stdio.h>
#include <math.h>
#include <string.h>
struct mykey{
    double a;
    int b;
};
struct mykey table[10][31];
char s[100];
const double EPS=1e-6;
int main(){
    int i,j,b,flag;
    double a1,b1,t,a;
    //i对应尾数为1的个数,j对应阶码为1的个数
    for(i=0;i<=9;i++){
        for(j=1;j<=30;j++){//以0.998046875*2^63转化为9.205357638345294*10^18为例,对应的i=8,j=6 
            a1=1-pow(2,-i-1);//十进制的尾数 0.998046875
            b1=pow(2,j)-1;//十进制的阶码 63
            t=log10(a1)+b1*log10(2);// log10(0.998046875*2^63)=log10(0.998046875)+63*log10(2)
            table[i][j].b=(int)t;//18
            table[i][j].a=pow(10,(t-table[i][j].b));//9.205357638345294
        }
    }
    while(scanf("%s",s)==1){//将字符串读取,处理成相应数字 
        if(strcmp("0e0",s)==0)//Uva11809对跳出while无判断,即有无判断0e0,程序都能AC,感兴趣的读者可以试一试. 
            break;
        a=s[0]-'0';//该数为个位数 
        for(i=2;i<=16;i++){//i=1是小数点,故从i=2开始 
            a+=(s[i]-'0')*pow(10,-i+1);//如十分位为*10^-1,百分位为*10^-2 
        }
        b=0;
        for(i=18;i<strlen(s);i++){
            b+=(int)((s[i]-'0')*pow(10,strlen(s)-1-i));//如个位为*10^0,十位为*10^1,百位为*10^2 
        }
        flag=0;
        for(i=0;i<=9;i++){
            for(j=1;j<=30;j++){
                if(fabs(a-table[i][j].a)<EPS&&b==table[i][j].b){//查表,注意double数据比较方式,int数据比较方式 
                    printf("%d %d\n",i,j);
                    flag=1;
                    break;//跳出内层的for(j=1...... 
                }
            }
            if(flag)
                break;//跳出外层的for(i=0...... 
        }
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值