这道题,是我目前写的行数最多的一道题(本人水平有限,写得比较菜),第一次超过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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 #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; else c[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 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 |
/*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.特别是他的模拟手算的部分,写的简练准确!