/* Program: poly-integer-root-v1.c (Report comments/bugs to chikh@yuntech.edu.tw) Function: 第二單元講義第21頁練習 Note: 針對多項式的表示方式,本程式未採書本polynomial.c的方式導入Dummy;本程式展示一個實作方式, 不使用Dummy仍可有效運作,供同學參考運用 */ #include #include /* for malloc(), abs() */ #include /* 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; }