POJ - 1001 Exponentiation(浮点数高精度乘法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cherish0222/article/details/78934637

今天信息学院的一个老师跟我讨论这个题,很遗憾我不会用Java的bigInteger类,只能手动用数组来模拟这个题了。

点我看题

题意:求r^n,其中0<r<99.99,0<n<=25.可以肯定的是,long double都存不下99.99^25,所以高精度了,这个题带有小数,那么我们首先要想起小学乘法里面的小数相乘问题,两个小数相乘,最后得到的结果中小数点位数等于乘数与被乘数的小数点位数之和。那这个题我们可以先记录下底数的小数点位数,然后将小数化为整数,最后就变成了整数相乘的高精度问题了,假设我们用数组a来保存乘数,数组b来保存被乘数(ab的高位保存的数的高位,所有下标从1开始),数组ans来存答案,那么我们根据所列的竖式可得:ans[i+j-1]+=a[i]*b[j]+add(add为进位),add=ans[i+j-1]/10,a[i+j-1]%=10;然后搞一搞答案就出来了。

参考代码:

#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<list>
#include<vector>
#include<iostream>

using namespace std;
char s[10];//底数
int r[10];//用整型数组来保存底数,且去掉小数点
int n;//指数
int tmp[1000];//临时变量,存储中间计算过程
int ans[1000];//用于保存最终结果
int point;//表示小数点位数

/*两个浮点数相乘,最终得到的浮点数的小数点位数是可以确定的,也就是乘数与被乘数小数点位数之和*/
int main()
{
    while( ~scanf("%s%d",s,&n))
    {
        //将输入的底数用整型数组来保存,且去掉小数点然后倒序,如12.34就存为4321,同时求出小数点位数
        int lens = strlen(s);
        int lenr = 1;
        bool flag = false;
        point = 0;
        for( int i = lens-1; i >= 0; i--)
        {
            if( s[i] != '.')
                r[lenr++] = s[i]-'0';
            else
                flag = true;
            //用于求小数点位数
            if( flag)
            {
                point = lens-i-1;
                flag = false;
            }
        }
        lenr--;

        //高精度乘法
        int lena = 1;
        memset(tmp,0,sizeof(tmp));
        memset(ans,0,sizeof(ans));
        tmp[1] = 1;
        for( int cnt = 0; cnt < n; cnt++)
        {
            for( int i = 1; i <= lena; i++)
            {
                int add = 0;
                for( int j = 1; j <= lenr; j++)
                {
                    ans[i+j-1] += tmp[i]*r[j]+add;
                    add = ans[i+j-1]/10;
                    ans[i+j-1] %= 10;
                }
                ans[i+lenr] = add;
            }

            lena += lenr;//计算答案的长度
            while( ans[lena] == 0 && lena > 1)//删除前导0
                lena--;
            if( cnt != n-1)
                for( int i = 1; i <= lena; i++)
                    tmp[i] = ans[i], ans[i] = 0;
        }


        //对结果的输出格式进行处理
        point *= n;//r^n共有point位小数
        if( lena <= point)//结果为纯小数
        {
            printf(".");
            for( int i = 1; i <= point-lena; i++)
                printf("0");
            int p = 0;
            while( ans[p] == 0 && p <= lena)//删除多余的0
                p++;
            for( int i = lena; i >= p; i--)
                printf("%d",ans[i]);
            puts("");
        }
        else//结果不为小数
        {
            int i;
            for( i = lena; i > point; i--)//输出整数部分
                printf("%d",ans[i]);
            int p = 0;
            while( ans[p] == 0 && p <= i)//删除后面多余的0
                p++;
            if( i >= p)
                printf(".");
            for( ; i >= p; i--)
                printf("%d",ans[i]);
            puts("");
        }
    }

    return 0;
}



阅读更多

北大 1001Exponentiation

05-09

小弟最近学习ACM,做了北大的1001题,使用的算法就是将结果放在一个整型数组里,数组的每个单元存储5位长的大于0的整数,每次都将R于整型数组的各个单元相乘,然后放在一个中间数组里,经过长度和进位的调整之后再放回整型数组,然后逐次计算,以达到求幂的效果,但是不过我咋样优化,就是超时啊,看网上有朋友也是同样算法就过了啊,很纠结,小弟用的C语言,直接上代码了,谢谢各位大虾!知道有种二分求幂的算法,但必须用那种么?rn#include "stdio.h"rn#include "math.h"rnmain()rnrn int result[32];rn double mid[32];rn int intInd;rn int fraInd;rn int n, i, j;rn double input;rn double max = 1;rn for(i=0; i<10; i++)rn max *= 10;rnrn while(scanf("%lf%d", &input, &n))rn rn double tmp1, tmp2;rn int add;rn intInd = 11;rn fraInd = 12;rn for(i=0; i<32; i++)rn mid[i] = 0.0;rn mid[intInd] = floor(input);rn result[intInd] = round(mid[intInd]);rn mid[fraInd] = (input-result[intInd]) * max;rn result[fraInd] = round(mid[fraInd]);rnrn for(j=1; j 0)rn fraInd++;rn for(i; i>=intInd; i--)rn rn mid[i] += add;rn add = 0;rn tmp1 = floor(mid[i]);rn tmp2 = mid[i] - tmp1;rn if(tmp2 > 0)rn rn add = round(tmp2 * max);rn mid[i] = tmp1;rn mid[i+1] += add;rn add = 0;rn if(mid[i+1] >= max)rn rn mid[i+1] -= max;rn mid[i] += 1;rn rn result[i+1] = round(mid[i+1]);rn rn if(mid[i] >= max)rn rn tmp1 = floor(mid[i]/max);rn mid[i] -= tmp1 * max;rn add = round(tmp1);rn rn result[i] = round(mid[i]);rn rn if(add > 0)rn result[--intInd] = add;rn rnrn if(intInd != 11 || result[11] != 0)rn rn printf("%d", result[intInd]);rn for(i=intInd+1; i<=11; i++)rn printf("%05d", result[i]);rn rn if(fraInd != 12 || result[12] != '0')rn rn printf("%c", '.');rn for(i=12; i 0.5)rn x += 1;rn return (int)x;rn

没有更多推荐了,返回首页