UVA 11809 Floating-Point Numbers

来源:互联网 发布:mac 强制重启finder 编辑:程序博客网 时间:2024/06/06 03:56

题意:

计算机常用阶码-尾数的方法保存浮点数。如图所示,如果阶码有6位,尾数有8位,可以表达的浮点数为0.111111111(2进制)*2^111111(2进制)。注意小数点后第一位必须为1,所以一共9位小数。这个数换成十进制之后就是0.998046875*2^63=9.205357638345294*10^18。现在需要根据这个最大浮点数,求出阶码的位数E和尾数的位数M。输入格式AeB,表示最大浮点数为A*10^B。0<A<10,并且恰好包含15位有效数字,对每组数据输出M和E。0<=M<=9,1<=E<=30

解题思路:如果直接根据最大浮点数计算会很麻烦,所以可以换种思维方式。因为M和E很小,所以直接打表就可以了。将阶码的位数和尾数的位数分别对应成十进制的数字,然后将输入的字符串转化成A*10^B的格式。m=0.1111...=2^(-0-1)+2^(-1-1)+2^(-2-1)+...+2(-i-1),等比数列求和可以得出m=1-2^(-i-1),同理e=111...=2^j-1。所以m*2^e=A*10^B,因为e可能会很大,所以不能直接这么算,两边同取lg,lg m+e*lg 2=lg A + B,所以B就是整数位,lgA就是小数位,然后查表就可以了

代码:

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <cstdio>using namespace std;double a[15][35];int b[15][35];void solve(){    for(int i=0; i<=9; i++)//打表    {        for(int j=1; j<=30; j++)        {            double m=1-pow(2,-1-i);            int e=pow(2,j)-1;            double k=log10(m)+e*log10(2);            int t=(int)k;            a[i][j]=k-t;            b[i][j]=t;        }    }}int main(){    string s;    solve();    while(cin>>s&&s!="0e0")    {        int len=s.length();        int pos1,pos2;        for(int i=0; i<len; i++)        {            if(s[i]=='.')pos1=i;            if(s[i]=='e')pos2=i;        }        long long int sum1=0,sum3=0;        double sum2=0;//sum2是浮点数        for(int i=0; i<pos1; i++)        {            sum1=sum1*10+(s[i]-'0');        }        for(int i=pos2-1; i>pos1; i--)//求小数        {            sum2+=(s[i]-'0');            sum2/=10;        }        for(int i=pos2+1; i<len; i++)        {            sum3=sum3*10+(s[i]-'0');        }        //cout<<sum1<<" "<<sum2<<" "<<sum3<<endl;        for(int i=0; i<=9; i++)//查表        {            for(int j=1; j<=30; j++)            {                if(fabs(log10(sum1+sum2)-a[i][j])<1e-4&&sum3==b[i][j])                {                    cout<<i<<" "<<j<<endl;                    break;                }            }        }    }    return 0;}


原创粉丝点击