[复习]高精度算法

今天又复习了一下高精度(高精度减、加、乘)

仍然用结构体来存储

数据结构:

typedef struct HP{

int w[10001]             //储存数据,0下标储存有多少位

}HP;

注意:高精度为了进位需要反着存储

例如:原数             a     123   -int

高精度数          b       3 |2|1 –int[]

  1. 加法

先将最大的位数+1,然后按位相加,每次加完进位,最后删除前导0

  1. 减法

和高精度加法类似,相当于就是加上一个负数,只是需要借位

在之前需要预处理一下,一定保证用大数减小数

  1. 乘法

虽然复习的是高精度乘单精度,但是我还是觉得直接用高精度乘比较简单

例如下面这个竖式:

1    2    3

×         1    2

-------------------------

2    4    6

1    2    3

------------------------

1    4    7    6

我们可以发现当HP a与HP b相乘时,a[i]*b[j]得到的是(i + j - 1)位上的数

下面附上源代码:

  1 /*
  2
  3  * [输入文件] hp.in
  4
  5  * 共三行
  6
  7  * 第一行和第二行是两个高精度数
  8
  9  * 第三行是一个符号(+ -或*)
 10
 11  * [输出文件] hp.out
 12
 13  * 仅一行,运算的结果
 14
 15  */
 16
 17 #include<iostream>
 18
 19 #include<string>
 20
 21 #include<cstring>
 22
 23 #include<cstdio>
 24
 25 using namespace std;
 26
 27 FILE *fp;
 28
 29 #ifndef _HPDEF_H_
 30
 31 #define _HPDEF_H_
 32
 33 typedef int HPI;
 34
 35 //高精度类
 36
 37 typedef struct
 38
 39 {
 40
 41       int w[10005];
 42
 43 }HP;
 44
 45 #endif
 46
 47 #ifndef _HP_H_
 48
 49 #define _HP_H_
 50
 51 //带成员函数的hp类
 52
 53 class hp{
 54
 55       public:
 56
 57       static HP hps(string str);
 58
 59       static HP add(HP *p1,HP *p2);
 60
 61       static HPI cmp(HP *p1,HP *p2);
 62
 63       static HP rem(HP *p1,HP *p2);
 64
 65       static void fout(HP *p);
 66
 67       static HP chen(HP *p1,HP *p2);
 68
 69 }hp;
 70
 71 /**
 72
 73  * 将字符串转化成高精度数
 74
 75  * @param str 要转化的字符串
 76
 77  * @return 转化后的高精度数
 78
 79  */
 80
 81 HP hp::hps(string str)
 82
 83 {
 84
 85       HP h;
 86
 87       memset(h.w,0,sizeof(h.w));
 88
 89       h.w[0]=str.size();
 90
 91       for(int i=h.w[0];i>=1;i--){
 92
 93            h.w[i]=str[(h.w[0]-i)]-‘0‘;
 94
 95       }
 96
 97       return h;
 98
 99 }
100
101 /**
102
103  * 将两个高精度数相加
104
105  * @param p1 第一个高精度数的地址
106
107  * @param p2 第二个高精度数的地址
108
109  * @return 计算的结果
110
111  */
112
113 HP hp::add(HP *p1,HP *p2)
114
115 {
116
117       HP p;
118
119       memset(p.w,0,sizeof(p.w));
120
121       if(p1->w[0]>p2->w[0]) p.w[0]=p1->w[0];
122
123       else p.w[0]=p2->w[0];
124
125       for(int i=1;i<=p.w[0];i++){
126
127            p.w[i]+=p1->w[i]+p2->w[i];
128
129            p.w[i+1]+=p.w[i]/10;
130
131            p.w[i]%=10;
132
133       }
134
135       p.w[0]+=2;
136
137       while(p.w[0]>1&&p.w[p.w[0]]==0) p.w[0]--;
138
139       return p;
140
141 }
142
143 /**
144
145  * 比较两个高精度数的大小
146
147  * @param p1 第一个高精度数的地址
148
149  * @param p2 第二个高精度数的地址
150
151  * @return 当*p1大于*p2时,返回1,<br>
152
153  *           当*p1小于*p2时,返回-1,<br>
154
155  *         否则返回0
156
157  */
158
159 HPI hp::cmp(HP *p1,HP *p2){
160
161       if(p1->w[0]>p2->w[0]) return 1;
162
163       else if(p1->w[0]<p2->w[0]) return -1;
164
165       for(int i=p1->w[0];i>=1;i--){
166
167            if(p1->w[i]>p2->w[i])
168
169                  return 1;
170
171            else if(p1->w[i]<p2->w[i])
172
173                  return -1;
174
175       }
176
177       return 0;
178
179 }
180
181 /**
182
183  * 将高精度数输出到文件流fp中
184
185  * @param p 要输出的高精度数的地址
186
187  */
188
189 void hp::fout(HP *p){
190
191       for(int i=p->w[0];i>=1;i--)
192
193       fprintf(fp,"%d",p->w[i]);
194
195 }
196
197 /**
198
199  * 将两个高精度数相减
200
201  * @param p1 被减高精度数的地址
202
203  * @param p2 减高精度数的地址
204
205  * @return 计算的结果
206
207  */
208
209 HP hp::rem(HP *p1,HP *p2){
210
211       HP p;
212
213       memset(p.w,0,sizeof(p.w));
214
215       p.w[0]=p1->w[0];
216
217       for(int i=1;i<=p.w[0];i++){
218
219            if(p1->w[i]<p2->w[i]){
220
221                  p1->w[i]+=10;
222
223                  p1->w[i+1]--;
224
225            }
226
227            p.w[i]=p1->w[i]-p2->w[i];
228
229       }
230
231       while(p.w[0]>1&&p.w[p.w[0]]==0) p.w[0]--;
232
233       return p;
234
235 }
236
237 /**
238
239  * 将两个高精度数相乘
240
241  * @param p1 第一个高精度数的地址
242
243  * @param p2 第二个高精度数的地址
244
245  * @return 计算的结果
246
247  */
248
249 HP hp::chen(HP *p1,HP *p2){
250
251       HP p;
252
253       memset(p.w,0,sizeof(p.w));
254
255       p.w[0]=p1->w[0]+p2->w[0];
256
257       for(int i=1;i<=p1->w[0];i++){
258
259            for(int j=1;j<=p2->w[0];j++){
260
261                  p.w[i+j-1]+=p1->w[i]*p2->w[j];
262
263                  p.w[i+j]+=p.w[i+j-1]/10;
264
265                  p.w[i+j-1]%=10;
266
267            }
268
269       }
270
271       p.w[0]+=2;
272
273       while(p.w[0]>1&&p.w[p.w[0]]==0) p.w[0]--;
274
275       return p;
276
277 }
278
279 #endif
280
281 int main(int argc,char* argv[])
282
283 {
284
285       freopen("gjc1.in","r",stdin);
286
287       fp=fopen("gjc1.out","w");
288
289       //局部变量定义
290
291       string str1,str2;
292
293       HP hp1,hp2,hp3;
294
295       char fu;
296
297       cin>>str1>>str2>>fu;
298
299       //转化字符串
300
301       hp1=hp::hps(str1);
302
303       hp2=hp::hps(str2);
304
305       fu = ‘*‘;
306
307       //计算
308
309       switch(fu){
310
311            case ‘+‘:
312
313                  hp3=hp::add(&hp1,&hp2);
314
315                  break;
316
317            case ‘-‘:
318
319                  switch(hp::cmp(&hp1,&hp2)){
320
321                       case 1:
322
323                             hp3=hp::rem(&hp1,&hp2);
324
325                             break;
326
327                       case 0:
328
329                             fprintf(fp,"0");
330
331                             return 0;
332
333                       case -1:
334
335                             hp3=hp::rem(&hp2,&hp1);
336
337                             fprintf(fp,"-");
338
339                             break;
340
341                  }
342
343                  break;
344
345             case ‘*‘:
346
347                  hp3=hp::chen(&hp1,&hp2);
348
349                  break;
350
351       }
352
353       hp::fout(&hp3);
354
355       return 0;
356
357 }
时间: 2024-10-14 14:01:41

[复习]高精度算法的相关文章

c++加法高精度算法

c++高精度算法,对于新手来说还是一大挑战,只要克服它,你就开启了编程的新篇章,算法. 我发的这个代码并不是很好,占用内存很多而且运行时间很长(不超过1秒),但是很好理解,很适合新手 高精算法的本质就是把数组编程字符串,然后将字符串像竖式一样加起来: 1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 using namespace std; 5 int main() 6 { 7 char a[

转载:C++之高精度算法

C++之高精度算法 注意:本文转载自http://blog.sina.com.cn/s/blog_4fdb102b010087ng.html,十分感谢原作者:忍者 前言:由于计算机运算是有模运算,数据范围的表示有一定限制,如整型int(C++中int 与long相同)表达范围是(-2^31~2^31-1),unsigned long(无符号整数)是(0~2^32-1),都约为几十亿.如果采用实数型,则能保存最大的double只能提供15~16位的有效数字,即只能精确表达数百万亿的数.因此,在计算

高精度算法

以下标程均为十进制,如改为10n进制可提高n倍速度. 建议不要使用operator对运算符进行重载,虽然用起来很方便,但是NOIP中不一定能用,速度也会慢一些. 高精度数大小比较 function a_dy_b(a,b:arr):boolean; var i:integer; begin i:=a[0]; if a[0]<>b[0] then a_dy_b:=a[0]>b[0] else begin while (a[i]=b[i])and(i>0) do dec(i); a_dy

LeetCode43,一题让你学会高精度算法

本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode系列第22篇文章,今天讲的内容是高精度算法. 今天和大家讨论的算法是高精度,对应的LeetCode是第43题.题面其实没什么好说的,以字符串的形式给定两个数字,要求返回这两个数字的乘积.之所以是以字符串的形式给数字是因为这个数字可能会非常大,题目当中给定的范围是110位的数字.对于Python来说这不是问题,但是对于C++和Java等语言来说这么大的数字是无法以int类型存储的,所以必须要使用字符串来接收. 如果你

卡特兰数高精度算法

很多组合题都会用到卡特兰数,增长速度又很快,应该写个高精度尊敬一下~ 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define ML 549 5 using namespace std; 6 int kt[105][550]; 7 int len[105]; 8 int getlen(int ord) 9 { 10 int pos; 11 for(int i=ML;i>=0;i

【个人模板】高精度算法

一.求两个高精度正数的和差积 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int MAXN=1000; 7 char s1[MAXN],s2[MAXN]; 8 int ed1,ed2,n1,n2; 9 int num1[MAXN]; 10 int num2[MAXN]; 11 int a

复习基础算法的感想

晚上做杭电OJ,第二题是一个比较直观的题,我也是太直观了.贴出代码,供自己反省,从7点15分一直做到结束,wa9次....orz....看来自己的算法功底还差的很远很远. 接下的几天,学习大白上的基础 算法部分. #include<iostream> #include<stdio.h> #include<cstring> using namespace std; char a[20],b[20]; char c[20]; void shuchu(int num) { i

c++ 高精度算法

包括: 两个高精度正整数加法 两个高精度正整数乘法 两个高精度正整数减法 两个高精度正整数除法 两个高精度正整数求余 两个高精度正整数数求最大公约数 两个高精度正整数数求最小公倍数 1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 //清除前缀0,如果结果是空字符串则设为0 7 inline void clear(string& a){ 8 while(a.length()>0

复习排序算法

一. 冒泡排序算法 1.第一次排序时将序列[0 ~ n - 1]中从前往后进行两个相邻元素的比较,若前者较大则交换,比较n-1次;当第一趟排序结束时,序列最大的元素就被交换到位置n-1上,就如同一个气泡,一步一步往后翻滚,直到最后一位. 2.重复步骤1,在第i趟时需要翻滚n-i-1次,每趟决定一个元素的位置,一共需要n-1趟. 比如,初始序列: [1, 5, 4, 3, 2] 第1趟: [1, 4, 3, 2 ] 5 第2趟: [1, 3, 2 ] 4, 5 ...... - (void)bub