这道题主要是考察数的高精度乘法,使用数组存储数据,数组中的元素对于高精度数据中的某一位。我用的思想很简单,类似我们手算乘法时采用的步骤,这是在两层的for()循环中实现的。需要注意一个问题,如果采用unsigned char型存储元素,在运算的过程中Rslt[]元素的中间结果可能超过255,造成乘法结果的中间部分数据不正确。因此,Rslt[]进行累加时,需要及时进位。在我的程序中,对数据有效位前后有0的情况做了处理,避免乘法过程中出现过多不必要的运算。但这也导致刚开始对10.0000这样的数据处理出现错误,后来用dotPos的正负表示小数点的位置,解决了此问题。
另外,对于高阶次幂,减少乘法使用的次数,采用降幂的思想。如2^9,可以看成(4^4)*2,进一步(16^2)*2。但是如何实现?这里,可以根据幂的二进制形式进行处理,如9表示成1001, 25表示成11001。具体见代码。注释部分采用这种思想,在VC运行通过。由于gcc没有对itoa实现,故submit的时候还用的传统方法。
#include <stdio.h>
/*#include <stdlib.h> */
#include <string.h>
unsigned char Rslt[200] = {0};
int do_multiple(unsigned char *MultiA, unsigned char *MultiB, int lenA, int lenB)
{
int i, j, k;
memset(Rslt, 0, sizeof(Rslt));
for(i = 0; i < lenA; i++)
{
for(j = 0; j < lenB; j++)
{
Rslt[i+j] += MultiA[i]*MultiB[j];
Rslt[i+j+1] += Rslt[i+j]/10;
Rslt[i+j] %= 10;
}
}
for(k = lenA+lenB-1; Rslt[k] == '\0'; k--){}
return (k+1);
}
int main(void)
{
int Power, dotPos;
int num_len, rslt_len;
/* char Power_buf[5]; */
char Num[10];
unsigned char ReverseNum[6];
unsigned char temp_rslt[200] = {0};
int i, j;
while(scanf("%s %d", Num, &Power) == 2)
{
/* itoa(Power, Power_buf, 2); */
dotPos = 0;
for(i = 0; Num[i] != '\0'; i++)
{
if(Num[i] != '.')
Num[i - (dotPos != 0)] = Num[i];
else
dotPos = i;
}
i -= (dotPos != 0);
for(--i; (Num[i] == '0'); i--){}
Num[i+1] = '\0';
num_len = strlen(Num);
dotPos = num_len - dotPos;
for(j = 0; i >= 0; i--)
{
ReverseNum[j++] = Num[i]-'0';
}
memcpy(Rslt, ReverseNum, num_len);
rslt_len = num_len;
for(i = 1; i < Power; i++)
{
memcpy(temp_rslt, Rslt, rslt_len);
rslt_len = do_multiple(temp_rslt, ReverseNum, rslt_len, num_len);
}
/* for(i = 1; i < (signed)strlen(Power_buf); i++)
{
memcpy(temp_rslt, Rslt, rslt_len);
rslt_len = do_multiple(temp_rslt, temp_rslt, rslt_len, rslt_len);
if(Power_buf[i] == '1')
{
memcpy(temp_rslt, Rslt, rslt_len);
rslt_len = do_multiple(temp_rslt, ReverseNum, rslt_len, num_len);
}
}
*/
dotPos *= Power;
if(dotPos >= rslt_len)
{
putchar('.');
for(i = dotPos; i > rslt_len; i--)
putchar('0');
}
for(i = rslt_len; i > 0; i--)
{
if(dotPos == i)
putchar('.');
putchar(Rslt[i-1]+'0');
}
while(dotPos++ < 0)
putchar('0');
putchar('\n');
}
return 0;
}