分治算法首先讲了一个经典的乘法运算
具体的代码如下: 该算法的核心是计算xy=(10^n/2xl+xr)(10^n/2yl+yr)=10^nxlyl+10^n/2(xlyr+xryl)+xryr
1 /************************************************************************/ 2 //函数功能:分治法求两个位数为N的整数的乘积 3 //输入参数:X,Y分别为两个位数为N的整数 4 //算法思想:分治算法,xy=(10n/2xl+xr)(10n/2yl+yr)=10nxlyl+10n/2(xlyr+xryl)+xryr 5 //时间复杂度为:T(n)=O(nlog3)=O(n1.59) 6 /************************************************************************/ 7 #include <iostream> 8 #include <cmath> 9 using namespace std; 10 #define SIGN(A) ((A > 0) ? 1 : -1) 11 12 int IntegerMultiply(int X, int Y, int N) 13 { 14 int sign = SIGN(X) * SIGN(Y); //确定结果的符号 15 int x = abs(X); //取绝对值,去掉x,y符号 16 int y = abs(Y); 17 if((0 == x) || (0 == y)) 18 return 0; 19 if (1 == N) 20 return x*y; 21 else 22 { 23 int XL = x / (int)pow(10., (int)N/2); 24 int XR = x - XL * (int)pow(10., N/2); 25 int YL = y / (int)pow(10., (int)N/2); 26 int YR = y - YL * (int)pow(10., N/2); 27 28 int XLYL = IntegerMultiply(XL, YL, N/2); 29 int XRYR = IntegerMultiply(XR, YR, N/2); 30 int XLYRXRYL = IntegerMultiply(XL - XR, YR - YL, N/2) + XLYL + XRYR; 31 return sign * (XLYL * (int)pow(10., N) + XLYRXRYL * (int)pow(10., N/2) + XRYR); 32 } 33 } 34 35 int main() 36 { 37 int x = 1234; 38 int y = 4321; 39 cout<<"x * y = "<<IntegerMultiply(x, y, 4)<<endl; 40 cout<<"x * y = "<<x*y<<endl; 41 return 0; 42 }
另外搜索到了一个很不错的大数程序,这里先mark一下:
1 //设计一个支持大数运算的计算器,其中乘法使用分治法求解。该计算器支持加减乘除还有开方根运算。 2 #include <iostream> 3 #include <list> 4 #include <string> 5 #include <cstdio> 6 #include <cctype> 7 #include <cmath> 8 using namespace std; 9 list<char> Add(list<char> s, list<char> t); 10 list<char> Sub(list<char> s, list<char> t); 11 list<char> Mul(list<char> s, list<char> t); 12 void Div(list<char> s, list<char> t); 13 void Root(list<char>); 14 void print(list<char> ans); 15 void printhelp() //打印帮助信息 16 { 17 cout << "请选择要进行的大数运算" << endl; 18 cout << "1:加法运算" << endl; 19 cout << "2:减法运算" << endl; 20 cout << "3:乘法运算" << endl; 21 cout << "4:除法运算" << endl; 22 cout << "5:开平方根运算" << endl; 23 cout << "6:退出" << endl; 24 } 25 list<char> Add(list<char> num1,list<char> num2) //加法运算 26 { 27 list<char> ans; 28 list<char>::iterator iter1,iter2; 29 iter1 = num1.begin(); 30 iter2 = num2.begin(); 31 int sign = 0; //标记结果符号 32 if((*iter1) == '-' && (*iter2) == '-') //如果两个数都是负数 33 { 34 num1.pop_front(); 35 num2.pop_front(); 36 sign = 1; 37 ans = Add(num1,num2); 38 ans.push_front('-'); 39 } 40 else if((*iter1) == '-' && (*iter2) != '-') //如果一负一正 41 { 42 num1.pop_front(); 43 ans = Sub(num2,num1); 44 45 } 46 else if((*iter1) != '-' && (*iter2) == '-') //如果一正一负 47 { 48 num2.pop_front(); 49 ans = Sub(num1,num2); 50 } 51 else //如果都为正 52 { 53 int len1,len2,i,len,carry; 54 len1 = num1.size(); 55 len2 = num2.size(); 56 if(len1 >= len2) //补齐两个数的位数 57 { 58 len = len1; 59 for(i = 0; i < len1 - len2; i++) 60 num2.push_front('0'); 61 } 62 else 63 { 64 len = len2; 65 for(i = 0; i < len2 - len1; i++) 66 num1.push_front('0'); 67 } 68 //print(num1); 69 //print(num2); 70 carry = 0; 71 iter1 = num1.end(); 72 iter2 = num2.end(); 73 iter1--; 74 iter2--; 75 for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2) //进行运算 76 { 77 i = (*iter1 - '0') + (*iter2 - '0') + carry; 78 //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; 79 ans.push_front((i % 10) + '0'); 80 carry = i / 10; 81 } 82 i = (*iter1 - '0') + (*iter2 - '0') + carry; 83 //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; 84 ans.push_front((i % 10) + '0'); 85 carry = i / 10; 86 if(carry) 87 ans.push_front(carry+'0'); 88 } 89 return ans; //返回结果 90 } 91 list<char> Sub(list<char> num1,list<char> num2) //减法运算 92 { 93 list<char> ans; 94 int sign = 0; 95 list<char>::iterator iter1,iter2; 96 int len1,len2,len; 97 iter1 = num1.begin(); 98 iter2 = num2.begin(); 99 if((*iter1) == '-' && (*iter2) == '-') //如果两个数都为负数 100 { 101 num2.pop_front(); 102 num1.pop_front(); 103 ans = Sub(num2,num1); 104 //ans.push_front('-'); 105 } 106 else if( (*iter1) == '-' && (*iter2) != '-') //如果一负一正 107 { 108 num1.pop_front(); 109 ans = Add(num1,num2); 110 ans.push_front('-'); 111 } 112 else if( (*iter1) != '-' && (*iter2) == '-') //如果一正一负 113 { 114 num2.pop_front(); 115 ans = Add(num1,num2); 116 117 } 118 else //如果都为正 119 { 120 len1 = num1.size(); 121 len2 = num2.size(); 122 if(len1 >= len2) //补齐位数 123 { 124 len = len1; 125 for(int i = 0; i < len1 - len2; i++) 126 num2.push_front('0'); 127 } 128 else 129 { 130 len = len2; 131 for(int i = 0; i < len2 - len1; i++) 132 num1.push_front('0'); 133 } 134 //print(num1);cout << endl; 135 //print(num2);cout << endl; 136 int carry = 0,i; 137 iter1 = num1.end(); 138 iter2 = num2.end(); 139 iter1--; 140 iter2--; 141 for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2) //进行运算 142 { 143 i = (*iter1 - '0' - carry) - (*iter2 - '0'); 144 carry = 0; 145 if( i < 0) 146 { 147 i += 10; 148 carry = 1; 149 } 150 //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; 151 ans.push_front((i % 10) + '0'); 152 } 153 i = (*iter1 - '0' - carry) - (*iter2 - '0'); 154 if(i < 0) 155 { 156 i += 10; 157 sign = 1; 158 } 159 //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; 160 if(i) ans.push_front(i + '0'); 161 if(sign) 162 ans.push_front('-'); 163 } 164 return ans; 165 } 166 list<char> Mul(list<char> num1,list<char> num2) // 分治法求两大数的积 167 { 168 list<char> ans; 169 int sign = 0; 170 int len1,len2,len; 171 list<char>::iterator iter1,iter2,iter; 172 list<char> high,low; 173 list<char> anshigh,anslow; 174 int th,tl; 175 int i,j,k; 176 //print(num1);cout << endl; 177 //print(num2);cout << endl; 178 if(num1.size() == 1 && num2.size() == 1) //如果两数都已是一位数,则进行运算 179 { 180 th = *(num1.begin()) - '0'; 181 tl = *(num2.begin()) - '0'; 182 th *= tl; 183 ans.push_front( th % 10 + '0'); 184 ans.push_front( th / 10 + '0'); 185 return ans; 186 } 187 else if(num1.size() == 1 && num2.size() > 1) //如果num1位数大于1,则对Num1分治求积 188 { 189 if(*(num2.begin()) == '-') 190 { 191 sign = 1; 192 num2.pop_front(); 193 } 194 len2 = num2.size(); 195 if(len2 == 1) 196 { 197 ans = Mul(num1,num2); 198 if(sign) 199 ans.push_front('-'); 200 } 201 else 202 { 203 for(iter= num2.begin(),i = 0; i < len2 / 2; i++,iter++) 204 { 205 high.push_back(*iter); 206 } 207 for(;iter!=num2.end();iter++) 208 { 209 low.push_back(*iter); 210 } 211 len = low.size(); 212 anshigh = Mul(num1,high); //num1分为两部分,high,low 213 anslow = Mul(num1,low); 214 for(i = 0; i < len; i++) 215 anshigh.push_back('0'); 216 ans = Add(anshigh,anslow); //合并结果 217 if(sign) 218 ans.push_front('-'); 219 } 220 return ans; 221 } 222 else if(num2.size() == 1 && num1.size() > 1) //如果num2位数大于1,则对Num2分治求积 223 { 224 if(*(num1.begin()) == '-') 225 { 226 sign = 1; 227 num1.pop_front(); 228 } 229 len1 = num1.size(); 230 if(len2 == 1) 231 { 232 ans = Mul(num1,num2); 233 if(sign) 234 ans.push_front('-'); 235 } 236 else 237 { 238 for(iter= num1.begin(),i = 0; i < len1 / 2; i++,iter++) 239 { 240 high.push_back(*iter); 241 } 242 for(;iter!=num1.end();iter++) 243 { 244 low.push_back(*iter); 245 } 246 len = low.size(); 247 anshigh = Mul(num2,high); //num2分为两部分,high,low 248 anslow = Mul(num2,low); 249 for(i = 0; i < len; i++) 250 anshigh.push_back('0'); 251 ans = Add(anshigh,anslow); //合并结果 252 if(sign) 253 ans.push_front('-'); 254 } 255 return ans; 256 } //如果两数位数都大于1,则都运用分治 257 else 258 { 259 list<char> num1high,num1low,num2high,num2low; 260 int flag1 = 0,flag2 = 0; 261 if(*(num1.begin()) == '-') 262 { 263 flag1 = 1; 264 num1.pop_front(); 265 } 266 if(*(num2.begin()) == '-') 267 { 268 flag2 = 1; 269 num2.pop_front(); 270 } 271 if((flag1 == 1 && flag2 == 0)||(flag1 == 0 && flag2 == 1)) //如果有一正一负,则标记结果为负 272 { 273 sign = 1; 274 } 275 len1 = num1.size(); 276 len2 = num2.size(); 277 if(len1 == 1 || len2 == 1) //如果有一个数是一位数,则直接递归调用 278 { 279 ans = Mul(num1,num2); 280 if(sign) 281 ans.push_front('-'); 282 } 283 else 284 { //否则分治法求 285 for(iter = num1.begin(),i = 0; i < len1 / 2; iter++,i++) 286 num1high.push_back(*iter); //被乘数高位部分 287 for( ; iter != num1.end(); iter++) 288 num1low.push_back(*iter); //被乘数低位部分 289 for(iter = num2.begin(),i = 0; i < len2 / 2; iter++,i++) 290 num2high.push_back(*iter); //乘数高位部分 291 for( ; iter != num2.end(); iter++) 292 num2low.push_back(*iter); //乘数低位部分 293 int a = (len1 + 1) / 2; 294 int b = (len2 + 1) / 2; 295 list<char> AC,AD,BC,BD; 296 //print(num2high);cout << endl; 297 //print(num2low);cout << endl; 298 AC = Mul(num1high,num2high); //运用X=A*10^a + B; Y= C*10^b + D; 299 AD = Mul(num1high,num2low); // X*Y = AC * 10 ^(a+b) + AD *10^a + BC * 10 ^b + BD公式求 300 BC = Mul(num1low,num2high); 301 BD = Mul(num1low,num2low); 302 for(i = 0; i < a + b; i++) 303 AC.push_back('0'); 304 for(i = 0; i < a; i++) 305 AD.push_back('0'); 306 for(i = 0; i < b; i++) 307 BC.push_back('0'); 308 ans = Add(AC,AD); 309 ans = Add(ans,BC); 310 ans = Add(ans,BD); //累加结果 311 if(sign) 312 ans.push_front('-'); 313 } 314 return ans; 315 } 316 } 317 void Div(list<char> num1,list<char> num2) //用辗转相除求结果 318 { 319 list<char> ans; 320 list<char> temp; 321 int len1,len2,len; 322 int i,j,k; 323 int sign = 0; 324 int flag1 = 0,flag2 = 0; 325 list<char>::iterator iter; 326 if(*(num1.begin()) == '-') 327 { 328 flag1 = 1; 329 num1.pop_front(); 330 } 331 if(*(num2.begin()) == '-') 332 { 333 flag2 = 1; 334 num2.pop_front(); 335 } 336 if((flag1 == 1 && flag2 != 1) || (flag1 == 0 && flag2 == 1)) 337 sign = 1; //标记结果符号 338 len1 = num1.size(); 339 len2 = num2.size(); 340 if(len1 < len2) //如果被除数小于除法,除数为0 341 { 342 cout << "商是0;余数是" ; 343 print(num2); 344 cout << endl; 345 return ; 346 } 347 else //用辗转相除求结果 348 { 349 for(iter = num1.begin(),i = 0; i < len2 ;++i,++iter) 350 temp.push_back(*iter); 351 list<char> digit,res; 352 for(j = 0; j < 10; j++) 353 { 354 digit.clear(); 355 digit.push_back(j + '0'); 356 res = Mul(num2,digit); 357 res = Sub(temp,res); 358 if(*(res.begin()) == '-') 359 break; 360 } 361 //cout << endl;print(temp); cout << endl; 362 j -= 1; 363 if(j > 0) 364 { 365 digit.clear(); 366 digit.push_back(j + '0'); 367 temp = Sub(temp,num2); 368 ans.push_back(j + '0'); 369 } 370 371 for(;iter != num1.end();++iter) 372 { 373 temp.push_back(*iter); 374 for(j = 0; j < 10; j++) 375 { 376 digit.clear(); 377 digit.push_back(j + '0'); 378 res = Mul(num2,digit); 379 res = Sub(temp,res); 380 if(*(res.begin()) == '-') 381 break; 382 } 383 //cout << endl;print(temp); cout << endl; 384 j -= 1; 385 digit.clear(); 386 digit.push_back(j + '0'); 387 res = Mul(num2,digit); 388 temp = Sub(temp,res); 389 ans.push_back(j + '0'); 390 } 391 if(sign) 392 ans.push_front('-'); 393 } 394 cout << "商是"; 395 print(ans); 396 cout << ";余数是" ; 397 print(temp); 398 cout << endl; 399 return ; 400 } 401 void Root(list<char> num1) //求大数的平方根,用枚举算法暴力搜索算法求 402 { 403 list<char> ans; 404 int len1; 405 list<char> digit,temp; 406 len1 = num1.size(); 407 int a = len1 / 2; //a是结果的最少位数 408 int i; 409 digit.push_back('1'); 410 ans.push_back('1'); //从ans=10 ^ a 开始搜索 411 for(i = 0; i < a - 1; i++) 412 ans.push_back('0'); 413 while(true) //搜到则结束 414 { 415 temp = Mul(ans,ans); 416 temp = Sub(num1,temp); 417 if(*(temp.begin()) == '-') //如果当前ans的平方大于num1,则得结果 418 break; 419 ans = Add(ans,digit); 420 } 421 ans = Sub(ans,digit); 422 print(ans); 423 cout << endl; 424 } 425 list<char> translate(string input) 426 { 427 list<char> res; 428 int len = input.length(); 429 for(int i = 0; i < len; i++) 430 res.push_back(input[i]); 431 return res; 432 } 433 void print(list<char> ans) 434 { 435 list<char>::iterator iter; 436 int flag = 1; 437 iter = ans.begin(); 438 if(*iter == '-') 439 { 440 cout << *iter; 441 iter++; 442 } 443 for(;iter != ans.end(); ++iter) 444 { 445 if(*iter == '0' && flag) 446 continue; 447 //cout << (*iter); 448 else 449 { 450 flag = 0; 451 cout << (*iter); 452 } 453 } 454 if( flag == 1) 455 cout << 0 ;; 456 //cout << endl; 457 } 458 int main() 459 { 460 char choice; //选择要进行的运算 461 list<char> num1; 462 list<char> num2; 463 list<char> res; 464 string input; 465 while(true) 466 { 467 cout << endl; 468 printhelp(); 469 cin >> choice; 470 switch(choice) 471 { 472 case '1': //如果选择加法运算 473 cout << "请输入第一个数" << endl; 474 cin >> input; 475 num1 = translate(input); 476 cout << "请输入第二个数" << endl; 477 cin >> input; 478 num2 = translate(input); 479 res = Add(num1,num2); 480 print(num1); 481 cout << " + " ; 482 print(num2); 483 cout << " = "; 484 print(res); 485 cout << endl; 486 break; 487 case '2': //选择减法运算 488 cout << "请输入第一个数" << endl; 489 cin >> input; 490 num1 = translate(input); 491 cout << "请输入第二个数" << endl; 492 cin >> input; 493 num2 = translate(input); 494 res = Sub(num1,num2); 495 print(num1); 496 cout <<" - " ; 497 print(num2); 498 cout << " = "; 499 print(res); 500 cout << endl; 501 break; 502 case '3': //选择乘法运算 503 cout << "请输入第一个数" << endl; 504 cin >> input; 505 num1 = translate(input); 506 cout << "请输入第二个数" << endl; 507 cin >> input; 508 num2 = translate(input); 509 res = Mul(num1,num2); 510 print(num1); 511 cout <<" * " ; 512 print(num2); 513 cout << " = "; 514 print(res); 515 cout << endl; 516 break; 517 case '4': //选择除法运算 518 cout << "请输入第一个数" << endl; 519 cin >> input; 520 num1 = translate(input); 521 cout << "请输入第二个数" << endl; 522 cin >> input; 523 num2 = translate(input); 524 print(num1); 525 cout << " / " ; 526 print(num2); 527 cout << " = "; 528 if(num2.size() == 1 && (*(num2.begin()) == '0')) 529 { 530 cout << "divided zero error" << endl; 531 break; 532 } 533 Div(num1,num2); 534 //print(res); 535 cout << endl; 536 break; 537 case '5': //选择求根运算 538 cout << "请输入第一个数" << endl; 539 cin >> input; 540 num1 = translate(input); 541 if(*(num1.begin()) == '-') 542 { 543 cout << "负数没有实数平方根" << endl; 544 break; 545 } 546 Root(num1); 547 break; 548 case '6': 549 return 0; 550 default: 551 break; 552 } 553 } 554 }