题意:
先介绍了浮点数的存储---用二进制数存储。浮点数(n)由尾数(mantissa)和阶码(exponent)组成。假设尾数和阶码的位数分别为M和E。按从左至右的顺序,首先是尾数的符号位(0代表正数,1代表负数),接下来是M位尾数部分,由于存储时尾数部分值一定是属于区间[0.5,1),所以M位尾数部分的第一位也就是整体的第二位一定是1。当M位尾数存储完了,第M+1位是阶码的符号位(0代表正数,1代表负数)。然后剩余E位用以保存阶码值。
例如:当M=8,E=6时,可以表示的最大浮点数(二进制)是;
利用二进制和十进制的转化规则可以将之转化为:
现在给出一个最大浮点数(用科学计数法AeB表示,且A有效数字15位),问存储时的尾数位数M和阶码位数E个位多少?
其中M取值区间[0,9],E取值区间[1,30]。
测试数据大概300行,0e0结束输入。
分析:
显然对于300行输入数据而且E的结果很可能很大,如果一个一个计算的话,会出现大量重复计算。可以用打表的方法:
预处理每个M和每个E对应的最大浮点数是多少,共300种匹配,然后对于每个输入,查找即可。
a[i][j]表示尾数位数为i,阶码位数为j时存储的最大浮点数。最大浮点数时,除了符号位其余位上都是1。
尾数部分存储数值为m[i],阶码部分存储数值为e[i][j]。通过二进制和十进制转换可得:m[i]=1-(1/2)^(i+1);e[j]=2^j-1;且a[i][j]=m[i]*2^(e[j])
但是如果这样直接存储数值太大了,所以取对数可得a[i][j]=>log10(m[i])+e[j]*log10(2),这样就可以打表了。
如果输入用AeB即A*10^B表示的话,也取对数可得log10(A)+B=t;
对于每个输入只需查找a[i][j]==t,输出对应的m[i]和e[j]即可。
至于A,B如何获取可以用sscanf函数。
sscanf() - 从一个字符串中读进与指定格式相符的数据.
函数原型:
Int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
int scanf( const char *format [,argument]... );
说明: