1 //数值计算程序-特征值和特征向量 2 3 ////////////////////////////////////////////////////////////// 4 //约化对称矩阵为三对角对称矩阵 5 //利用Householder变换将n阶实对称矩阵约化为对称三对角矩阵 6 //a-长度为n*n的数组,存放n阶实对称矩阵 7 //n-矩阵的阶数 8 //q-长度为n*n的数组,返回时存放Householder变换矩阵 9 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 10 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 11 void eastrq(double a[],int n,double q[],double b[],double c[]); 12 ////////////////////////////////////////////////////////////// 13 //求实对称三对角对称矩阵的全部特征值及特征向量 14 //利用变型QR方法计算实对称三对角矩阵全部特征值及特征向量 15 //n-矩阵的阶数 16 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 17 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 18 //q-长度为n*n的数组,若存放单位矩阵,则返回实对称三对角矩阵的特征向量组 19 // 若存放Householder变换矩阵,则返回实对称矩阵A的特征向量组 20 //a-长度为n*n的数组,存放n阶实对称矩阵 21 int ebstq(int n,double b[],double c[],double q[],double eps,int l); 22 ////////////////////////////////////////////////////////////// 23 //约化实矩阵为赫申伯格(Hessen berg)矩阵 24 //利用初等相似变换将n阶实矩阵约化为上H矩阵 25 //a-长度为n*n的数组,存放n阶实矩阵,返回时存放上H矩阵 26 //n-矩阵的阶数 27 void echbg(double a[],int n); 28 ////////////////////////////////////////////////////////////// 29 //求赫申伯格(Hessen berg)矩阵的全部特征值 30 //返回值小于0表示超过迭代jt次仍未达到精度要求 31 //返回值大于0表示正常返回 32 //利用带原点位移的双重步QR方法求上H矩阵的全部特征值 33 //a-长度为n*n的数组,存放上H矩阵 34 //n-矩阵的阶数 35 //u-长度为n的数组,返回n个特征值的实部 36 //v-长度为n的数组,返回n个特征值的虚部 37 //eps-控制精度要求 38 //jt-整型变量,控制最大迭代次数 39 int edqr(double a[],int n,double u[],double v[],double eps,int jt); 40 ////////////////////////////////////////////////////////////// 41 //求实对称矩阵的特征值及特征向量的雅格比法 42 //利用雅格比(Jacobi)方法求实对称矩阵的全部特征值及特征向量 43 //返回值小于0表示超过迭代jt次仍未达到精度要求 44 //返回值大于0表示正常返回 45 //a-长度为n*n的数组,存放实对称矩阵,返回时对角线存放n个特征值 46 //n-矩阵的阶数 47 //u-长度为n*n的数组,返回特征向量(按列存储) 48 //eps-控制精度要求 49 //jt-整型变量,控制最大迭代次数 50 int eejcb(double a[],int n,double v[],double eps,int jt); 51 ////////////////////////////////////////////////////////////// 52 53 54 55 选自<<徐世良数值计算程序集(C)>> 56 57 每个程序都加上了适当地注释,陆陆续续干了几个月才整理出来的啊。 58 59 今天都给贴出来了 60 61 #include "stdio.h" 62 #include "math.h" 63 //约化对称矩阵为三对角对称矩阵 64 //利用Householder变换将n阶实对称矩阵约化为对称三对角矩阵 65 //a-长度为n*n的数组,存放n阶实对称矩阵 66 //n-矩阵的阶数 67 //q-长度为n*n的数组,返回时存放Householder变换矩阵 68 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 69 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 70 void eastrq(double a[],int n,double q[],double b[],double c[]) 71 { 72 int i,j,k,u,v; 73 double h,f,g,h2; 74 for (i=0; i<=n-1; i++) 75 { 76 for (j=0; j<=n-1; j++) 77 { 78 u=i*n+j; q[u]=a[u]; 79 } 80 } 81 for (i=n-1; i>=1; i--) 82 { 83 h=0.0; 84 if (i>1) 85 { 86 for (k=0; k<=i-1; k++) 87 { 88 u=i*n+k; 89 h=h+q[u]*q[u]; 90 } 91 } 92 93 if (h+1.0==1.0) 94 { 95 c[i-1]=0.0; 96 if (i==1) 97 { 98 c[i-1]=q[i*n+i-1]; 99 } 100 b[i]=0.0; 101 } 102 else 103 { 104 c[i-1]=sqrt(h); 105 u=i*n+i-1; 106 if (q[u]>0.0) 107 { 108 c[i-1]=-c[i-1]; 109 } 110 h=h-q[u]*c[i-1]; 111 q[u]=q[u]-c[i-1]; 112 f=0.0; 113 for (j=0; j<=i-1; j++) 114 { 115 q[j*n+i]=q[i*n+j]/h; 116 g=0.0; 117 for (k=0; k<=j; k++) 118 { 119 g=g+q[j*n+k]*q[i*n+k]; 120 } 121 if (j+1<=i-1) 122 { 123 for (k=j+1; k<=i-1; k++) 124 { 125 g=g+q[k*n+j]*q[i*n+k]; 126 } 127 } 128 c[j-1]=g/h; 129 f=f+g*q[j*n+i]; 130 } 131 h2=f/(h+h); 132 for (j=0; j<=i-1; j++) 133 { 134 f=q[i*n+j]; 135 g=c[j-1]-h2*f; 136 c[j-1]=g; 137 for (k=0; k<=j; k++) 138 { 139 u=j*n+k; 140 q[u]=q[u]-f*c[k-1]-g*q[i*n+k]; 141 } 142 } 143 b[i]=h; 144 } 145 } 146 b[0]=0.0; 147 for (i=0; i<=n-1; i++) 148 { 149 if ((b[i]!=0.0)&&(i-1>=0)) 150 { 151 for (j=0; j<=i-1; j++) 152 { 153 g=0.0; 154 for (k=0; k<=i-1; k++) 155 { 156 g=g+q[i*n+k]*q[k*n+j]; 157 } 158 for (k=0; k<=i-1; k++) 159 { 160 u=k*n+j; 161 q[u]=q[u]-g*q[k*n+i]; 162 } 163 } 164 } 165 u=i*n+i; 166 b[i]=q[u]; 167 q[u]=1.0; 168 if (i-1>=0) 169 { 170 for (j=0; j<=i-1; j++) 171 { 172 q[i*n+j]=0.0; 173 q[j*n+i]=0.0; 174 } 175 } 176 } 177 return; 178 179 180 181 182 //求实对称三对角对称矩阵的全部特征值及特征向量 183 //利用变型QR方法计算实对称三对角矩阵全部特征值及特征向量 184 //n-矩阵的阶数 185 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 186 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 187 //q-长度为n*n的数组,若存放单位矩阵,则返回实对称三对角矩阵的特征向量组 188 // 若存放Householder变换矩阵,则返回实对称矩阵A的特征向量组 189 //a-长度为n*n的数组,存放n阶实对称矩阵 190 int ebstq(int n,double b[],double c[],double q[],double eps,int l) 191 { 192 int i,j,k,m,it,u,v; 193 double d,f,h,g,p,r,e,s; 194 c[n-1]=0.0; 195 d=0.0; 196 f=0.0; 197 for (j=0; j<=n-1; j++) 198 { 199 it=0; 200 h=eps*(fabs(b[j])+fabs(c[j])); 201 if (h>d) 202 { 203 d=h; 204 } 205 m=j; 206 while ((m<=n-1)&&(fabs(c[m])>d)) 207 { 208 m=m+1; 209 } 210 if (m!=j) 211 { 212 do 213 { 214 if (it==l) 215 { 216 printf("fail\n"); 217 return(-1); 218 } 219 it=it+1; 220 g=b[j]; 221 p=(b[j+1]-g)/(2.0*c[j]); 222 r=sqrt(p*p+1.0); 223 if (p>=0.0) 224 { 225 b[j]=c[j]/(p+r); 226 } 227 else 228 { 229 b[j]=c[j]/(p-r); 230 } 231 h=g-b[j]; 232 for (i=j+1; i<=n-1; i++) 233 { 234 b[i]=b[i]-h; 235 } 236 f=f+h; 237 p=b[m]; 238 e=1.0; 239 s=0.0; 240 for (i=m-1; i>=j; i--) 241 { 242 g=e*c[i]; 243 h=e*p; 244 if (fabs(p)>=fabs(c[i])) 245 { 246 e=c[i]/p; 247 r=sqrt(e*e+1.0); 248 c[i+1]=s*p*r; 249 s=e/r; 250 e=1.0/r; 251 } 252 else 253 { 254 e=p/c[i]; 255 r=sqrt(e*e+1.0); 256 c[i+1]=s*c[i]*r; 257 s=1.0/r; 258 e=e/r; 259 } 260 p=e*b[i]-s*g; 261 b[i+1]=h+s*(e*g+s*b[i]); 262 for (k=0; k<=n-1; k++) 263 { 264 u=k*n+i+1; 265 v=u-1; 266 h=q[u]; 267 q[u]=s*q[v]+e*h; 268 q[v]=e*q[v]-s*h; 269 } 270 } 271 c[j]=s*p; 272 b[j]=e*p; 273 } 274 while (fabs(c[j])>d); 275 } 276 b[j]=b[j]+f; 277 } 278 for (i=0; i<=n-1; i++) 279 { 280 k=i; p=b[i]; 281 if (i+1<=n-1) 282 { 283 j=i+1; 284 while ((j<=n-1)&&(b[j]<=p)) 285 { 286 k=j; 287 p=b[j]; 288 j=j+1; 289 } 290 } 291 if (k!=i) 292 { 293 b[k]=b[i]; 294 b[i]=p; 295 for (j=0; j<=n-1; j++) 296 { 297 u=j*n+i; 298 v=j*n+k; 299 p=q[u]; 300 q[u]=q[v]; 301 q[v]=p; 302 } 303 } 304 } 305 return(1); 306 } 307 308 //约化实矩阵为赫申伯格(Hessen berg)矩阵 309 //利用初等相似变换将n阶实矩阵约化为上H矩阵 310 //a-长度为n*n的数组,存放n阶实矩阵,返回时存放上H矩阵 311 //n-矩阵的阶数 312 void echbg(double a[],int n) 313 { int i,j,k,u,v; 314 double d,t; 315 for (k=1; k<=n-2; k++) 316 { 317 d=0.0; 318 for (j=k; j<=n-1; j++) 319 { 320 u=j*n+k-1; 321 t=a[u]; 322 if (fabs(t)>fabs(d)) 323 { 324 d=t; 325 i=j; 326 } 327 } 328 if (fabs(d)+1.0!=1.0) 329 { 330 if (i!=k) 331 { 332 for (j=k-1; j<=n-1; j++) 333 { 334 u=i*n+j; 335 v=k*n+j; 336 t=a[u]; 337 a[u]=a[v]; 338 a[v]=t; 339 } 340 for (j=0; j<=n-1; j++) 341 { 342 u=j*n+i; 343 v=j*n+k; 344 t=a[u]; 345 a[u]=a[v]; 346 a[v]=t; 347 } 348 } 349 for (i=k+1; i<=n-1; i++) 350 { 351 u=i*n+k-1; 352 t=a[u]/d; 353 a[u]=0.0; 354 for (j=k; j<=n-1; j++) 355 { 356 v=i*n+j; 357 a[v]=a[v]-t*a[k*n+j]; 358 } 359 for (j=0; j<=n-1; j++) 360 { 361 v=j*n+k; 362 a[v]=a[v]+t*a[j*n+i]; 363 } 364 } 365 } 366 } 367 return; 368 } 369 370 371 372 //求赫申伯格(Hessen berg)矩阵的全部特征值 373 //利用带原点位移的双重步QR方法求上H矩阵的全部特征值 374 //返回值小于0表示超过迭代jt次仍未达到精度要求 375 //返回值大于0表示正常返回 376 //a-长度为n*n的数组,存放上H矩阵 377 //n-矩阵的阶数 378 //u-长度为n的数组,返回n个特征值的实部 379 //v-长度为n的数组,返回n个特征值的虚部 380 //eps-控制精度要求 381 //jt-整型变量,控制最大迭代次数 382 int edqr(double a[],int n,double u[],double v[],double eps,int jt) 383 { 384 int m,it,i,j,k,l,ii,jj,kk,ll; 385 double b,c,w,g,xy,p,q,r,x,s,e,f,z,y; 386 it=0; 387 m=n; 388 while (m!=0) 389 { 390 l=m-1; 391 while ((l>0)&&(fabs(a[l*n+l-1])>eps*(fabs(a[(l-1)*n+l-1])+fabs(a[l*n+l])))) 392 { 393 l=l-1; 394 } 395 ii=(m-1)*n+m-1; 396 jj=(m-1)*n+m-2; 397 kk=(m-2)*n+m-1; 398 ll=(m-2)*n+m-2; 399 if (l==m-1) 400 { 401 u[m-1]=a[(m-1)*n+m-1]; 402 v[m-1]=0.0; 403 m=m-1; it=0; 404 } 405 else if (l==m-2) 406 { 407 b=-(a[ii]+a[ll]); 408 c=a[ii]*a[ll]-a[jj]*a[kk]; 409 w=b*b-4.0*c; 410 y=sqrt(fabs(w)); 411 if (w>0.0) 412 { 413 xy=1.0; 414 if (b<0.0) 415 { 416 xy=-1.0; 417 } 418 u[m-1]=(-b-xy*y)/2.0; 419 u[m-2]=c/u[m-1]; 420 v[m-1]=0.0; v[m-2]=0.0; 421 } 422 else 423 { 424 u[m-1]=-b/2.0; 425 u[m-2]=u[m-1]; 426 v[m-1]=y/2.0; 427 v[m-2]=-v[m-1]; 428 } 429 m=m-2; 430 it=0; 431 } 432 else 433 { 434 if (it>=jt) 435 { 436 printf("fail\n"); 437 return(-1); 438 } 439 it=it+1; 440 for (j=l+2; j<=m-1; j++) 441 { 442 a[j*n+j-2]=0.0; 443 } 444 for (j=l+3; j<=m-1; j++) 445 { 446 a[j*n+j-3]=0.0; 447 } 448 for (k=l; k<=m-2; k++) 449 { 450 if (k!=l) 451 { 452 p=a[k*n+k-1]; 453 q=a[(k+1)*n+k-1]; 454 r=0.0; 455 if (k!=m-2) 456 { 457 r=a[(k+2)*n+k-1]; 458 } 459 } 460 else 461 { 462 x=a[ii]+a[ll]; 463 y=a[ll]*a[ii]-a[kk]*a[jj]; 464 ii=l*n+l; 465 jj=l*n+l+1; 466 kk=(l+1)*n+l; 467 ll=(l+1)*n+l+1; 468 p=a[ii]*(a[ii]-x)+a[jj]*a[kk]+y; 469 q=a[kk]*(a[ii]+a[ll]-x); 470 r=a[kk]*a[(l+2)*n+l+1]; 471 } 472 if ((fabs(p)+fabs(q)+fabs(r))!=0.0) 473 { 474 xy=1.0; 475 if (p<0.0) 476 { 477 xy=-1.0; 478 } 479 s=xy*sqrt(p*p+q*q+r*r); 480 if (k!=l) 481 { 482 a[k*n+k-1]=-s; 483 } 484 e=-q/s; 485 f=-r/s; 486 x=-p/s; 487 y=-x-f*r/(p+s); 488 g=e*r/(p+s); 489 z=-x-e*q/(p+s); 490 for (j=k; j<=m-1; j++) 491 { 492 ii=k*n+j; 493 jj=(k+1)*n+j; 494 p=x*a[ii]+e*a[jj]; 495 q=e*a[ii]+y*a[jj]; 496 r=f*a[ii]+g*a[jj]; 497 if (k!=m-2) 498 { 499 kk=(k+2)*n+j; 500 p=p+f*a[kk]; 501 q=q+g*a[kk]; 502 r=r+z*a[kk]; 503 a[kk]=r; 504 } 505 a[jj]=q; 506 a[ii]=p; 507 } 508 j=k+3; 509 if (j>=m-1) 510 { 511 j=m-1; 512 } 513 for (i=l; i<=j; i++) 514 { 515 ii=i*n+k; 516 jj=i*n+k+1; 517 p=x*a[ii]+e*a[jj]; 518 q=e*a[ii]+y*a[jj]; 519 r=f*a[ii]+g*a[jj]; 520 if (k!=m-2) 521 { 522 kk=i*n+k+2; 523 p=p+f*a[kk]; 524 q=q+g*a[kk]; 525 r=r+z*a[kk]; 526 a[kk]=r; 527 } 528 a[jj]=q; 529 a[ii]=p; 530 } 531 } 532 } 533 } 534 } 535 return(1); 536 } 537 538 539 540 //求实对称矩阵的特征值及特征向量的雅格比法 541 //利用雅格比(Jacobi)方法求实对称矩阵的全部特征值及特征向量 542 //返回值小于0表示超过迭代jt次仍未达到精度要求 543 //返回值大于0表示正常返回 544 //a-长度为n*n的数组,存放实对称矩阵,返回时对角线存放n个特征值 545 //n-矩阵的阶数 546 //u-长度为n*n的数组,返回特征向量(按列存储) 547 //eps-控制精度要求 548 //jt-整型变量,控制最大迭代次数 549 int eejcb(double a[],int n,double v[],double eps,int jt) 550 { 551 int i,j,p,q,u,w,t,s,l; 552 double fm,cn,sn,omega,x,y,d; 553 l=1; 554 for (i=0; i<=n-1; i++) 555 { 556 v[i*n+i]=1.0; 557 for (j=0; j<=n-1; j++) 558 { 559 if (i!=j) 560 { 561 v[i*n+j]=0.0; 562 } 563 } 564 } 565 while (1==1) 566 { 567 fm=0.0; 568 for (i=0; i<=n-1; i++) 569 { 570 for (j=0; j<=n-1; j++) 571 { 572 d=fabs(a[i*n+j]); 573 if ((i!=j)&&(d>fm)) 574 { 575 fm=d; 576 p=i; 577 q=j; 578 } 579 } 580 } 581 if (fm<eps) 582 { 583 return(1); 584 } 585 if (l>jt) 586 { 587 return(-1); 588 } 589 l=l+1; 590 u=p*n+q; 591 w=p*n+p; 592 t=q*n+p; 593 s=q*n+q; 594 x=-a[u]; 595 y=(a[s]-a[w])/2.0; 596 omega=x/sqrt(x*x+y*y); 597 if (y<0.0) 598 { 599 omega=-omega; 600 } 601 sn=1.0+sqrt(1.0-omega*omega); 602 sn=omega/sqrt(2.0*sn); 603 cn=sqrt(1.0-sn*sn); 604 fm=a[w]; 605 a[w]=fm*cn*cn+a[s]*sn*sn+a[u]*omega; 606 a[s]=fm*sn*sn+a[s]*cn*cn-a[u]*omega; 607 a[u]=0.0; 608 a[t]=0.0; 609 for (j=0; j<=n-1; j++) 610 { 611 if ((j!=p)&&(j!=q)) 612 { 613 u=p*n+j; 614 w=q*n+j; 615 fm=a[u]; 616 a[u]=fm*cn+a[w]*sn; 617 a[w]=-fm*sn+a[w]*cn; 618 } 619 } 620 for (i=0; i<=n-1; i++) 621 { 622 if ((i!=p)&&(i!=q)) 623 { 624 u=i*n+p; 625 w=i*n+q; 626 fm=a[u]; 627 a[u]=fm*cn+a[w]*sn; 628 a[w]=-fm*sn+a[w]*cn; 629 } 630 } 631 for (i=0; i<=n-1; i++) 632 { 633 u=i*n+p; 634 w=i*n+q; 635 fm=v[u]; 636 v[u]=fm*cn+v[w]*sn; 637 v[w]=-fm*sn+v[w]*cn; 638 } 639 } 640 return(1); 641 }
转自:http://www.cnblogs.com/longdouhzt/archive/2012/04/22/2465191.html