NYOJ 155题 求高精度幂

来源:互联网 发布:ppt图表编辑数据没反应 编辑:程序博客网 时间:2024/05/21 10:17

这道题,是我目前写的行数最多的一道题(本人水平有限,写得比较菜),第一次超过100行了,哈哈,有点自嘲的意味。

首先,总体上要有一个思路,从样例中看出,位数很多,正常的一些类型肯定不能表示出来,我选择了字符串来接收所谓的R,将它的每一位在放到数组里面。想想,乘法怎么去实现。实数,考虑到有小数点,那么就要确定小数的位数了。下面是程序代码,仅供参考。

 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100101102103104105106107108109110111112113114115116117118119120121122123124125
#include<stdio.h>#include<stdlib.h>#include<string.h>int main(){char ch[11];int n;while(scanf("%s ", ch) != EOF){scanf("%d", &n);if(n == 0)printf("1");else{int len, flag = -1, out, m;int i, j = 0, k = 0;int input[11] = {0}, output[2000] = {0}, temp[2000] = {0};//input最开始的数,output最终结果,temp保留中间过程的数;len = strlen(ch);char str[11] = {0};char c[11] = {0};for(i = 0; i < len; i ++) //找到小数点位置;{if(ch[i] == '.')flag = i;elsec[k ++] = ch[i]; //将ch中的字符 除小数点外 都按顺序赋给c;}len = strlen(c);int p = 0;if((flag == -1) || ((i- 1) == flag)) //12300和12300.这种情况;{for(i = len - 1; i >= 0; i --){if(c[i] != '0'){p = (len - 1 - i) * n;//计算整数位上 后面有几个0;break;}}}for(i = len - 1; i >= 0; i --)//将c倒序赋给str;{str[j ++] = c[i];}for(i = strlen(ch) - 1; i >= 0; i --)//对于有小数点的,找出小数有多少位;{if((ch[i] != '0') && (flag != -1))//找的时候特别注意1.0100这种情况;{flag = (i - flag) * n;break;}}len = strlen(str); j = 0;k = 0;int a, b;//a,b从两边去掉 运算时 无效的0;for(i = 0; i < len; i ++){if(str[i] != '0'){a = i;break;}}for(i = len - 1; i >= 0; i --){if(str[i] != '0'){b = i;break; }}for(i = a; i <= b; i ++)//给output初始化;output[k ++] = input[j ++] = str[i] - '0';out = j;//out是output里面元素的个数;for(i = 0; i < n - 1; i ++)//整个for循环是 模拟手算;n次幂,循环乘(n-1)次;{for(j = 0; j < (b- a + 1); j ++)//input是(b-a+1)位,其每一位都要与 output 相乘;{int l = j, c[2000] = {0}, s[2000] = {0};for(k = 0; k < out; k ++)//input中的第j位分别与output中的每一位相乘;{s[l] = (c[l] + input[j] * output[k]) % 10;//本位和;c[l + 1] = (c[l] + input[j] * output[k]) / 10;//进位位;temp[l] += s[l];l ++; }if(c[l] != 0){temp[l] = c[l];l = l + 1;}m = l;}out = m;int tempc[2000] = {0};for(m = 0; m < out ; m ++)//计算一次 幂 ,错位相加 计算所得结果{output[m] = (temp [m] + tempc[m]) % 10;tempc[m + 1] = (temp [m] + tempc[m]) / 10;}if(tempc[m] != 0){output[m] = tempc[m];out = out + 1;}memset(temp, 0, sizeof(temp));//注意将temp清零;}if(out <= flag)printf(".");for(i = flag - out; i > 0; i --)printf("0"); //补 0 ;for(i = out - 1; i >= 0; i--){printf("%d", output[i]);//倒序输出output;if(i == flag)printf(".");//在小数点的位置,打印出小数点}for(i = 0; i < p; i ++)printf("0");//对应于上面的 12300 和 12300. ,输出有效0;}printf("\n");}return 0;}



下面是比较专业的程序,当然,不是我写的大笑

1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
/*155*//*能看懂这个程序,也不是一件容易事啊*/#include<stdio.h>#include<stdlib.h>#include<string.h>int result[1001];//全局变量,开始就是0!char a[11];int top1, top2;void fun(int num){int i, j;for(i = 0; i < top1; i++)//result中的每一位分别与num相乘;{result[i] = result[i] * num;}for(i = 0; i < top1; i++)//处理进位,和加;{result[i + 1] += result[i] /10;result[i] = result[i] % 10;//注意,这里是倒序存放到result里面的;if(i + 1 == top1 && result[i + 1] != 0)top1 ++;//最终的top1 代表一共有top1位;}}int main(){int flag;char str[11];int num;int n;int i;int len;double number;while(~scanf("%s", str)){scanf("%d", &num);flag = -1;number = atof(str);sprintf(str, "%.10g", number);len = strlen(str);top1 = 1;top2 = 0;result[0] = 1;for(i = 0; str[i]; i++)//找到小数点的位置;{if(str[i] =='.')flag = i;else {a[top2++] = str[i];//将小数点去掉,再存放到a里面;}}if(flag != -1)//计算n次幂求完之后,小数一共多少位;{flag = len - (flag + 1);//flag = len - 1 - flag;flag *= num;//flag = flag * num;}n = atoi(a);//将字符串转换成长整型数;for(i = 0; i < num; i ++)//num次幂,循环num次;{fun(n);}if(top1 - 1 < flag)//如果所求的top1 <= flag时,打印出小数点printf(".");for(i = flag - top1; i> 0; i --)//如果top1 < flag即所求位数不足小数点后的位数,要补零;printf("0");for(i = top1 - 1; i >= 0; i--){if((i + 1) == flag)//循环到小数点的位置时,添上小数点;printf(".");printf("%d", result[i]);//将result中的所有数倒序输出;}printf("\n");memset(a, 0, sizeof(a));//完成一次求高精度幂之后,将a result进行初始化;memset(result, 0, sizeof(result));}return 0;}

从学长的程序中,能学到好多东西:
1.while(~ scanf("%s", str))
2.atof : 字符串转换成浮点数,12345.67->12345.670000
3.sprintf : 送格式化输出到字符串
4.atoi : 字符串转换成长整型数12345.67 -> 12345
5.atol : 字符串转换成长整型数,98765432->98765432
6.memset : 设置s中的所有字节为ch,s数组的大小由n给定 void *memset(void *s, char ch, unsigned n)
7.全局变量!一上来就是 0 ~~~
8.特别是他的模拟手算的部分,写的简练准确!

原创粉丝点击