NYOJ 155题 求高精度幂

这道题,是我目前写的行数最多的一道题(本人水平有限,写得比较菜),第一次超过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.特别是他的模拟手算的部分,写的简练准确!





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值