POJ1001 Exponentiation--浮点数的高精度乘法

POJ1001 Exponentiation(浮点数的高精度乘法)

Description

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. 
This problem requires that you write a program to compute the exact value of R n where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.

Sample Input

95.123 12

0.4321 20
5.1234 15
6.7592  9
98.999 10
1.0100 12
Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201
 
 
 
题意:给定一个浮点数R( 0.0 <  R< 99.999 ) 和整数N(0 < n <= 25),求R n 。

题解:此类题目由于结果会超出浮点数的范围,所以采用高精度保存数据并计算。

本题具体作法:一、预处理输入的字符串(读入数据以字符串的格式)
			1.先除去字符串(即R)前面的0,直到碰到非零(包括小数点)为止。
			2.除去字符串后面的0(先判断是否含有小数点):
			   如果含有小数点:从末尾开始去0,一直去到非零位置,或者碰到小数点(这里和前面不一样,如果碰到要把小数点			   也去掉);
			   如果不含小数点,既R为整数,后面的0自然不用除去。
		    二、计算(设处理后的R存在dig数组里-----存的时候要逆序存,这点要注意
				当然要分类讨论,先考虑特殊情况,当n==1时,直接输出处理后的R值。
				若n!=0,则需计算,如下:
				1.将R值先赋值给一个二维数组的第一行,如mul[0][300];
		2.然后就是依次拿mul[0][300]和{R的每一位}相乘,将与每一位计算所得的值分别放在mul[1][300]
				mul[2][300]...---------这里R每一位与之相乘时注意:每次所得的数要依次在前面的基础下往后挪一位;	                                                 还有相乘是别忘了进位。
	     3.将mul[1][300]mul[k][300](设dig有k位数,既R处理后留下的数字的个数)相加所得的值重新赋值	mul[0][300],此时已经完成了R^2,接下来只需要将mul[0][300]不断与R相乘直到n次为止。
	三、结果的处理和输出
	   如果是R整数,当然结果无需处理可以直接输出了,当然要逆序输出,而且要从末尾非零的数开始读。
	   但是如果是R是小数的话,就不一样了,还是分类讨论:
	   1.如果位数不够要在小数点后面加0,并且第一位是小数点;
	   2.够了的话确定小数点在什么位置。

下面是我写的代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char num[10];
int sum[300],mul[30][300],dig[10],c[300];
int main()
{
    int n;
    while(scanf("%s%d",num,&n)!=EOF)
    {
        memset(sum,0,sizeof(sum));
        memset(mul,0,sizeof(mul));
        memset(dig,0,sizeof(dig));
        int m,count,l,i,j,k,d,wei,flag=0;
        m=strlen(num);
        for(i=0;i<m;i++)
        {
            if(num[i]=='.') flag=1;
        }
        for(i=0;i<m;i++)
        {
            if(num[i]=='0')
            {
                for(j=i;j<m;j++)
                {
                    num[j]=num[j+1];
                }
                m--;
                i--;
            }
            else break;
        }
        if(flag)
        {
            for(i=m-1;i>=0;i--)
            {
                if(num[i]=='0')
                {
                    num[i]='\0';
                    m--;
                }
                else break;
            }
            if(num[m-1]=='.')
            {
                num[m-1]='\0';
                m--;
            }
        }
        k=0;
        wei=m-1;
        for(i=m-1;i>=0;i--)
        {
            if(num[i]=='.') wei=i;
            else
            {
                mul[0][k++]=num[i]-'0';
                dig[k-1]=mul[0][k-1];
            }
        }
        d=m-1-wei;
        count=d*n;
        for(i=2;i<=n;i++)
        {
            l=0;
            for(j=0;j<8;j++)
            {
                for(k=0;k<300;k++)
                {
                    mul[j+1][k+l]=dig[j]*mul[0][k];
                }
            l++;
            }
            memset(sum,0,sizeof(sum));
            for(k=0;k<300;k++)
            {
                for(j=0;j<8;j++)
                {
                    sum[k]+=mul[j+1][k];
                }
                c[k+1]=(sum[k]+c[k])/10;
                sum[k]=(sum[k]+c[k])%10;
                mul[0][k]=sum[k];
            }
        }
        for(i=299;i>=0;i--)
        {
            if(mul[0][i]) break;
        }
        if(!count)
        {
            for(j=i;j>=0;j--)
            {
                printf("%d",mul[0][j]);
            }
        }
        else if(count-i-1<=0)
        {
            for(j=i;j>=0;j--)
            {
                printf("%d",mul[0][j]);
                if(j==count) printf(".");
            }
        }
        else if(count-i-1>0)
        {
            printf(".");
            for(j=1;j<=count-i-1;j++)
            {
                printf("0");
            }
            for(j=i;j>=0;j--)
            {
                printf("%d",mul[0][j]);
            }
        }
        printf("\n");
    }
}






                                  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值