uva 11809 - Floating-Point Numbers(浮点数)

习题3-12 浮点数(Floating-Point Numbers, UVa11809)
计算机常用阶码-尾数的方法保存浮点数。如图3-9所示,如果阶码有6位,尾数有8位,可以表达的最大浮点数为0.1111111112×2
1111112。注意小数点后第一位必须为1,所以一共有9位小数。
图3-9 阶码-尾数保存浮点数
这个数换算成十进制之后就是0.998046875*2^63=9.205357638345294*10^18。你的任务是根据这个最大浮点数,求出阶码的位数E和尾数的位数M。输入格式为AeB,表示最大浮点数为A*10B。0< A<10,并且恰好包含15位有效数字。输 入结束标志为0e0。对于每组数据,输
出M和E。输入保证有唯一解,且0≤M≤9,1≤E≤30。在本题中,M+E+2不必为8的整数倍。
Sample Input
5.699141892149156e76
9.205357638345294e18
0e0
Sample Output
5 8
8 6

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=830&problem=2909&mosmsg=Submission+received+with+ID+20702100

  1. 我们只要算:m*2^(2^n-1)=f *10^t (m是浮点数位,n是阶码位数,求f和t;)
  2. 而f=10^log10(f):即左边=10^t1=10^(t+log10(f));
  3. t1=log10(m*2^(2^n-1))=log10(m)+(2^n-1) *log10(2)
  4. t=(int)t1; f=10^(t1-t);
    感谢参考来自http://blog.csdn.net/crazysillynerd/article/details/43339157
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
double flo[10][30];
int expstr[10][30];
int main()
{
    int twoe;
    double twom;
    double temp;
    for(int i=0;i<10;i++)
    {
        twom=1-pow(2,-i-1);
        for(int j=0;j<30;j++)
        {
            twoe = pow(2,j+1)-1;
            temp = log10(twom)+twoe*log10(2);
            expstr[i][j]=temp;
            flo[i][j]=pow(10,(temp-expstr[i][j]));
        }
    }
    while(1)
    {
        double flo1;
        int exp1;
        char str[25]={0};//存输入的浮点数字符串
        int iff=0;

        //输入浮点数
        char c;
        for(int i=0;(c=getchar())!='e';i++)
        {
            str[i]=c;//scanf("%c",&str[i]);
        }
        sscanf(str,"%lf",&flo1);
        scanf("%d",&exp1);

        if(flo1==0&&exp1==0)//结束标志
            break;

        //从表中找最接近的小数
        for(int i=0;i<10;i++)
        {
            for(int j=0;j<30;j++)
            {
                //cout<<flo[i][j]<<"  "<<expstr[i][j]<<endl;
                if(abs(flo[i][j]-flo1)<10e-6&&
                   exp1==expstr[i][j])
                {
                    cout<<i;
                    cout<<" "<<j+1<<endl;
                    iff=1;
                    break;
                }
            }
             if(iff==1)break;
        }
    }
    return 0;
}
//AC at 2018/2/1

(另外提供几个样例
in
6.741349255732847e307
1.937500000000000e0
8.970910077290883e307
2.734479740168092e20201780
5.443088840828674e2465
7.100722886226033e80807123
7.499999999999997e0
4.461493107584252e4931
7.930743765436021e78912
1.638399999999996e4
6.284909967160199e153
5.794969071594055e40403561
7.874999999999996e0
7.049550013794259e78912
5.205075292180178e4931
2.094479696316021e323228496
5.999999999999998e0
7.513237239003285e19727
2.065788087458129e323228496
5.112881885711930e2465
0e0
out
1 10
4 1
8 10
0 26
8 13
6 28
3 2
1 14
5 18
0 4
3 9
4 27
5 2
2 18
2 14
8 30
1 2
1 16
5 30
3 13

说来心酸:第一个思路:将输入的以十为底的小数化为以二为底的,是直接一位一位冥次死算出的。并且转换后,运用到十进制小数转二进制,先不论麻烦至极和时间耗费太久,最重要的是这样精度的问题会很大。(失败)
第二思路:网上查询后,要打表,好。费尽脑筋思考怎么将十为底的小数化为以二为底的数,看网上说用10=1.25*2^3来推,是的这样可以,但是表打出来就要花9s,绝对的超时。

(题外话:这道题一开始做还是在去年,当时写好了第一种思路以为很快就可以通过,于是之后考试复习就没有再管。就这样断断续续一个多月才终于把这道题做出来。)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值