这道题主要说了浮点数在二进制的存储方式,比如0.111111*2^111111,尾数位数算是5位,
前面的0.1本来会有的,那么尾数就等于1-2^(-i-1)(等比数列的求和公式),另一个就为
2^(2^j-1),然后直接打表就行了,因为(1-2^(-i-1))*2^(2^j-1)=A*B^10,这个数太大,所
以可以对两边取对数保存,整数部分是B,小数部分就是A(log10(A)<1)。
#include <cstdio>
#include <sstream>
#include <iostream>
#include <cmath>
#define eps 1e-4
#define LL long long
using namespace std;
const int N = 20, M = 35;
LL E[N][M];
double man[N][M];
int main ( )
{
string str;
double A, m, e;
LL B;
for ( int i = 0; i < N; i ++ ) //打表
for ( int j = 0; j < M; j ++ )
{
m = 1-pow ( 2, -i-1 ); //不能用右移,因为-i-1是负数
e = ( 1 << j )-1;
double t = log10 ( m )+e*log10 ( 2 );
E[i][j] = ( LL ) t; //其实b就是整数部分
man[i][j] = pow ( 10.0, t-E[i][j] );
//因为0<a<10,log10(a)<1就是小数部分,即10^(t-(LL)t)
/*if ( i == 0 )
printf ( "%.2lf %lld\n", man[i][j], E[i][j] );*/
}
while ( cin >> str && str != "0e0" )
{
for ( int i = 0; i < str.size ( ); i ++ )
if ( str[i] == 'e' )
{
str[i] = ' '; //把e变成空格
break ;
}
stringstream ss ( str );
ss >> A >> B;
//cout << A << " " << B << endl;
int flag = 0;
for ( int i = 0; i < 10; i ++ ) //注意这里只能用10和31,用N M就WA
for ( int j = 0; j < 31; j ++ )
{
if ( B == E[i][j] && fabs ( A-man[i][j] ) < eps ) //只需要判断是否小于等于1e-4就行了
{
flag = 1;
printf ( "%d %d\n", i, j );
break ;
}
if ( flag )
break ;
}
}
return 0;
}