[ACM Steps]2.3.2 Exponentiation 大数乘法 小数的n次幂

来源:互联网 发布:安卓主题知乎 编辑:程序博客网 时间:2024/05/01 18:20

题目:http://acm.hdu.edu.cn/game/entry/problem/show.php?chapterid=2&sectionid=3&problemid=2


求一个大数(小数或整数)的n 次幂。


思路:

1、大数乘法

首先,将两个操作数逆转存放。

然后,将第i位和第j位相乘的结果累加存入得数的第i+j位。

再处理进位,把进位加到下一位。

最后确定得数的位数。一个A位数和一个B位数相乘的结果最长为A+B位。从得数的A+B位开始,判断是否为0,若为0 ,则得数长度减1.。

Number mul(Number A,Number B){Number C;int carry;for(int i = 0;i < A.len;i++)for(int j = 0;j < B.len;j++){C.num[i + j] += (A.num[i] * B.num[j]);}int len = A.len + B.len ;carry = 0;for(int i = 0;i < len;i++){C.num[i] += carry;if(C.num[i] > 9){carry = C.num[i] / 10;C.num[i] = C.num[i] % 10;}else carry = 0;}while(C.num[len - 1] == 0){len--;}C.len = len;return C;}



2、小数点位置

整数的n次幂必定为整数,小数的N次幂则为小数(0次幂除外),所以要确定得数小数点位置。

一个有m位小数的数的n次幂,得数有m*n位小数。


消除后置0

在处理输入数时,先判断是否存在小数点。若存在,删除小数点最后的0。

然后求出小数点后的数字位数,即小数的位数。

在完成乘法后,可能需要在小数点后补0

根据得数的长度与得数小数位数比较,

若小数位数 >= 得数长度,小数点在最前面,小数点后需要补小数点位数 - 得数长度个0.

否则,则在得数中的小数点位置插入小数点。


#include <stdio.h>#include <string.h>struct Number{int num[200];int len;Number(){memset(num,0,sizeof(num));len = 0;}};Number mul(Number A,Number B){Number C;int carry;for(int i = 0;i < A.len;i++)for(int j = 0;j < B.len;j++){C.num[i + j] += (A.num[i] * B.num[j]);}int len = A.len + B.len ;carry = 0;for(int i = 0;i < len;i++){C.num[i] += carry;if(C.num[i] > 9){carry = C.num[i] / 10;C.num[i] = C.num[i] % 10;}else carry = 0;}while(C.num[len - 1] == 0){len--;}C.len = len;return C;}int main(){int n,len;char R[200];Number A;Number Ans;int decimalPoint;bool decimalPointFlag;while(scanf("%s %d",R,&n) != EOF){len = strlen(R);decimalPoint = 0;decimalPointFlag = false;A.len = 0;for(int i = 0;i < len;i++)//是否为小数if(R[i] == '.')decimalPointFlag = true;if(decimalPointFlag)while(R[len -1] == '0')//去除小数点后最后多余的0len--;for(int i = len - 1; i >= 0 ; i--){if(R[i] == '.')decimalPoint = len - i - 1;//小数点后数字的位数else A.num[A.len++] = R[i] - '0';}Ans.num[0] = 1;Ans.len = 1;decimalPoint *= n;while(n--){Ans = mul(Ans,A);}if(Ans.len == 0)printf("%c", '0');if(decimalPoint >= Ans.len)//小数点位数 >= 得数长度时,要在最前面补小数点{printf("%c", '.');for(int i = 0;i < decimalPoint - Ans.len;i++)//得数长度小于小数点位数时,要补0printf("%c", '0');}for(int i = Ans.len - 1;i >= 0;i--){printf("%d", Ans.num[i]);if(decimalPoint != 0 && i == decimalPoint)printf("%c", '.');}printf("\n");}return 0;}


0 0
原创粉丝点击