88 lines
3.6 KiB
C
88 lines
3.6 KiB
C
/*
|
||
Program: poly-integer-root-v1.c (Report comments/bugs to chikh@yuntech.edu.tw)
|
||
Function: 第二單元講義第21頁練習
|
||
Note: 針對多項式的表示方式,本程式未採書本polynomial.c的方式導入Dummy;本程式展示一個實作方式,
|
||
不使用Dummy仍可有效運作,供同學參考運用
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h> /* for malloc(), abs() */
|
||
#include <math.h> /* for pow() */
|
||
|
||
int findRoot(int p[], int q[]) /* p:輸入的多項式;q:求得的整數根 */
|
||
{
|
||
int r, c = 0, i, j, k, sum;
|
||
int sign[2] = {1,-1};
|
||
|
||
if (p[2*p[0]]%p[2] != 0) return 0; /* 多項式的常數項若不能被最高階項的係數整除(譬如2x^2 - 3 = 0),則不存在整數解 */
|
||
|
||
r = abs(p[2*p[0]]/p[2]); /* r:能遍除多項式係數的因數,目的令最高階項的係數簡化為±1而常數項簡化為±r,以利後續運算 */
|
||
for (i = 1; i <= r; i++) { /* 考慮r的所有因數i,若i正好能令多項式函數為0,則該因數i即為所求解之一 */
|
||
if (r%i != 0) continue; /* 此i無法整除r,i不是r的因數,故略過,繼續考慮下一個i */
|
||
for (j = 0; j < 2; j++) { /* 導入此2回合的迴圈係因±i都可能是解,j為0,代表考慮+i的情境;j為1,代表考慮-i的情況 */
|
||
for (sum = 0, k = 1; k <= 2*p[0]; k+=2) /* 計算每一項的結果值(係數*x^指數)並累加到sum之中 */
|
||
sum += p[k+1]*(int)(pow(sign[j]*i,p[k])); /* ±i之值以sign[j]*i實現,代入多項式內對應的項次求相應之值 */
|
||
if (sum == 0) q[c++] = sign[j]*i; /* bingo! 發現合乎條件的整數根,將其寫入q陣列內 */
|
||
}
|
||
}
|
||
|
||
return c; /* 回傳解的個數 */
|
||
}
|
||
|
||
void show(int p[], int n, int mode) /* 輸入的p陣列可能描述多項式,也可能代表整數根的內容,將由mode區分差異化的處理方式 */
|
||
{
|
||
int i;
|
||
|
||
if (mode == 0) { /* mode為0,代表p將被解讀為多項式之描述資訊,將顯示該多項式 */
|
||
printf("方程式p(x)= ");
|
||
for (i = 1; i <= n; i += 2) {
|
||
if (abs(p[i+1])>1) /* 項係數不為±1 */
|
||
printf("%s%d",p[i+1]>1? "":"\b", p[i+1]); /* 若係數>1,可直接顯示係數值;若係數為負,則游標倒退一格再顯示係數值(把前導的'+'號塗掉) */
|
||
else if (p[i+1]==-1) /* 項係數為-1 */
|
||
printf("\b-"); /* 游標倒退一格,隨後僅再顯示'-'號即可(前導的'+'號塗掉)(不需顯示為'-1') */
|
||
/* 項係數若為1,則不用額外動作;保留前導的'+',毋需另作更動 */
|
||
switch(p[i]) { /* switch架構處理每個項次內指數的部分 */
|
||
case 0: /* 該項指數為0,意為常數項,不需顯示x^0,故僅顯示'+'號,為下一項的輸出作準備 */
|
||
printf("+");
|
||
break;
|
||
case 1:
|
||
printf("x+"); /* 該項指數為1,不需顯示x^1,故僅顯示'x+',為下一項的輸出作準備 */
|
||
break;
|
||
default:
|
||
printf("x^%d+",p[i]); /* 顯示x^n+形式,為下一項的輸出作準備 */
|
||
}
|
||
}
|
||
printf("\b "); /* 最後多餘的'+'號以空白塗掉 */
|
||
}
|
||
else { /* mode為1,代表p將被解讀為多項式之根,將顯示根的內容 */
|
||
for (i = 0; i < n; i++) printf("%d、",p[i]); /* 每秀出一個根,之後另顯示頓號 */
|
||
if (n > 0) printf("\b\b "); /* 最後顯示多餘的頓號以游標倒退二格的方式改以空白塗掉 */
|
||
}
|
||
}
|
||
|
||
int main()
|
||
{
|
||
int p[] = {4,3,1,2,-2,1,-1,0,2};
|
||
//int p[] = {4,3,3,2,-6,1,-3,0,6};
|
||
//int p[] = {2,2,1,0,-100};
|
||
//int p[] = {4,3,1,2,-7,1,4,0,12};
|
||
//int p[] = {5,4,1,3,3,2,-66,1,52,0,120};
|
||
//int p[] = {5,4,3,3,9,2,-198,1,156,0,360};
|
||
int c, *q = (int *)malloc(p[1]*sizeof(int)); /* p[1]紀錄最高階項之指數,依此值創建足夠元素空間的陣列存放所求得的整數根 */
|
||
/* c: 求得的整數根的個數,將紀錄findRoot()回傳的根個數;
|
||
q: 存放求得根所用陣列,根的個數最多與多項式最高階項之指數相同,以p的屬性動態配置所需記憶體空間 */
|
||
|
||
printf("\n*** 解多項式之整數根 ***\n\n");
|
||
show(p,2*p[0],0); /* 秀出以p描述的多項式,2*p[0]代表描述非零項所用的數值個數,第三引數0為輸出模式(詳見底下show()的定義) */
|
||
c = findRoot(p,q); /* 執行求根程序,輸入p所描述的多項式,q將紀錄求得的根,findRoot()回傳符合的根個數 */
|
||
if (c > 0) {
|
||
printf("\n\n解得整數根為:");
|
||
show(q,c,1); /* 秀出q的內容,c為根的個數,第三引數1代表呼叫show()運行所需的工作模式 */
|
||
}
|
||
else
|
||
printf("\n\n整數根不存在\n");
|
||
|
||
free(q);
|
||
return 0;
|
||
}
|